Index: lib/Target/Mips/AsmParser/MipsAsmParser.cpp =================================================================== --- lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -195,7 +195,6 @@ OperandMatchResultTy parseImm(OperandVector &Operands); OperandMatchResultTy parseJumpTarget(OperandVector &Operands); OperandMatchResultTy parseInvNum(OperandVector &Operands); - OperandMatchResultTy parseMovePRegPair(OperandVector &Operands); OperandMatchResultTy parseRegisterList(OperandVector &Operands); bool searchSymbolAlias(OperandVector &Operands); @@ -760,7 +759,6 @@ k_RegisterIndex, /// A register index in one or more RegKind. k_Token, /// A simple token k_RegList, /// A physical register list - k_RegPair /// A pair of physical register } Kind; public: @@ -778,7 +776,6 @@ delete RegList.List; case k_RegisterIndex: case k_Token: - case k_RegPair: break; } } @@ -1038,6 +1035,17 @@ Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); } + void addGPRMM16AsmRegMovePPairFirstOperands(MCInst &Inst, unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); + } + + void addGPRMM16AsmRegMovePPairSecondOperands(MCInst &Inst, + unsigned N) const { + assert(N == 1 && "Invalid number of operands!"); + Inst.addOperand(MCOperand::createReg(getGPRMM16Reg())); + } + /// Render the operand to an MCInst as a GPR64 /// Asserts if the wrong number of operands are requested, or the operand /// is not a k_RegisterIndex compatible with RegKind_GPR @@ -1217,29 +1225,6 @@ Inst.addOperand(MCOperand::createReg(RegNo)); } - void addRegPairOperands(MCInst &Inst, unsigned N) const { - assert(N == 2 && "Invalid number of operands!"); - assert((RegIdx.Kind & RegKind_GPR) && "Invalid access!"); - unsigned RegNo = getRegPair(); - AsmParser.warnIfRegIndexIsAT(RegNo, StartLoc); - Inst.addOperand(MCOperand::createReg( - RegIdx.RegInfo->getRegClass( - AsmParser.getABI().AreGprs64bit() - ? Mips::GPR64RegClassID - : Mips::GPR32RegClassID).getRegister(RegNo++))); - Inst.addOperand(MCOperand::createReg( - RegIdx.RegInfo->getRegClass( - AsmParser.getABI().AreGprs64bit() - ? Mips::GPR64RegClassID - : Mips::GPR32RegClassID).getRegister(RegNo))); - } - - void addMovePRegPairOperands(MCInst &Inst, unsigned N) const { - assert(N == 2 && "Invalid number of operands!"); - for (auto RegNo : getRegList()) - Inst.addOperand(MCOperand::createReg(RegNo)); - } - bool isReg() const override { // As a special case until we sort out the definition of div/divu, accept // $0/$zero here so that MCK_ZERO works correctly. @@ -1406,34 +1391,6 @@ bool isRegList() const { return Kind == k_RegList; } - bool isMovePRegPair() const { - if (Kind != k_RegList || RegList.List->size() != 2) - return false; - - unsigned R0 = RegList.List->front(); - unsigned R1 = RegList.List->back(); - - if ((R0 == Mips::A1 && R1 == Mips::A2) || - (R0 == Mips::A1 && R1 == Mips::A3) || - (R0 == Mips::A2 && R1 == Mips::A3) || - (R0 == Mips::A0 && R1 == Mips::S5) || - (R0 == Mips::A0 && R1 == Mips::S6) || - (R0 == Mips::A0 && R1 == Mips::A1) || - (R0 == Mips::A0 && R1 == Mips::A2) || - (R0 == Mips::A0 && R1 == Mips::A3) || - (R0 == Mips::A1_64 && R1 == Mips::A2_64) || - (R0 == Mips::A1_64 && R1 == Mips::A3_64) || - (R0 == Mips::A2_64 && R1 == Mips::A3_64) || - (R0 == Mips::A0_64 && R1 == Mips::S5_64) || - (R0 == Mips::A0_64 && R1 == Mips::S6_64) || - (R0 == Mips::A0_64 && R1 == Mips::A1_64) || - (R0 == Mips::A0_64 && R1 == Mips::A2_64) || - (R0 == Mips::A0_64 && R1 == Mips::A3_64)) - return true; - - return false; - } - StringRef getToken() const { assert(Kind == k_Token && "Invalid access!"); return StringRef(Tok.Data, Tok.Length); @@ -1481,11 +1438,6 @@ return *(RegList.List); } - unsigned getRegPair() const { - assert((Kind == k_RegPair) && "Invalid access!"); - return RegIdx.Index; - } - static std::unique_ptr CreateToken(StringRef Str, SMLoc S, MipsAsmParser &Parser) { auto Op = llvm::make_unique(k_Token, Parser); @@ -1593,18 +1545,6 @@ return Op; } - static std::unique_ptr CreateRegPair(const MipsOperand &MOP, - SMLoc S, SMLoc E, - MipsAsmParser &Parser) { - auto Op = llvm::make_unique(k_RegPair, Parser); - Op->RegIdx.Index = MOP.RegIdx.Index; - Op->RegIdx.RegInfo = MOP.RegIdx.RegInfo; - Op->RegIdx.Kind = MOP.RegIdx.Kind; - Op->StartLoc = S; - Op->EndLoc = E; - return Op; - } - bool isGPRZeroAsmReg() const { return isRegIdx() && RegIdx.Kind & RegKind_GPR && RegIdx.Index == 0; } @@ -1640,6 +1580,19 @@ (RegIdx.Index >= 16 && RegIdx.Index <= 20)); } + bool isMM16AsmRegMovePPairFirst() const { + if (!(isRegIdx() && RegIdx.Kind)) + return false; + return RegIdx.Index >= 4 && RegIdx.Index <= 6; + } + + bool isMM16AsmRegMovePPairSecond() const { + if (!(isRegIdx() && RegIdx.Kind)) + return false; + return (RegIdx.Index == 21 || RegIdx.Index == 22 || + (RegIdx.Index >= 5 && RegIdx.Index <= 7)); + } + bool isFGRAsmReg() const { // AFGR64 is $0-$15 but we handle this in getAFGR64() return isRegIdx() && RegIdx.Kind & RegKind_FGR && RegIdx.Index <= 31; @@ -1720,9 +1673,6 @@ OS << Reg << " "; OS << ">"; break; - case k_RegPair: - OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">"; - break; } } @@ -2288,6 +2238,22 @@ if (Inst.getOperand(0).getReg() == Mips::RA) return Error(IDLoc, "invalid operand for instruction"); break; + case Mips::MOVEP_MM: + case Mips::MOVEP_MMR6: { + unsigned R0 = Inst.getOperand(0).getReg(); + unsigned R1 = Inst.getOperand(1).getReg(); + bool RegPair = ((R0 == Mips::A1 && R1 == Mips::A2) || + (R0 == Mips::A1 && R1 == Mips::A3) || + (R0 == Mips::A2 && R1 == Mips::A3) || + (R0 == Mips::A0 && R1 == Mips::S5) || + (R0 == Mips::A0 && R1 == Mips::S6) || + (R0 == Mips::A0 && R1 == Mips::A1) || + (R0 == Mips::A0 && R1 == Mips::A2) || + (R0 == Mips::A0 && R1 == Mips::A3)); + if (!RegPair) + return Error(IDLoc, "invalid operand for instruction"); + break; + } } } @@ -6278,45 +6244,6 @@ return MatchOperand_Success; } -OperandMatchResultTy -MipsAsmParser::parseMovePRegPair(OperandVector &Operands) { - MCAsmParser &Parser = getParser(); - SmallVector, 8> TmpOperands; - SmallVector Regs; - - if (Parser.getTok().isNot(AsmToken::Dollar)) - return MatchOperand_ParseFail; - - SMLoc S = Parser.getTok().getLoc(); - - if (parseAnyRegister(TmpOperands) != MatchOperand_Success) - return MatchOperand_ParseFail; - - MipsOperand *Reg = &static_cast(*TmpOperands.back()); - unsigned RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg(); - Regs.push_back(RegNo); - - SMLoc E = Parser.getTok().getLoc(); - if (Parser.getTok().isNot(AsmToken::Comma)) { - Error(E, "',' expected"); - return MatchOperand_ParseFail; - } - - // Remove comma. - Parser.Lex(); - - if (parseAnyRegister(TmpOperands) != MatchOperand_Success) - return MatchOperand_ParseFail; - - Reg = &static_cast(*TmpOperands.back()); - RegNo = isGP64bit() ? Reg->getGPR64Reg() : Reg->getGPR32Reg(); - Regs.push_back(RegNo); - - Operands.push_back(MipsOperand::CreateRegList(Regs, S, E, *this)); - - return MatchOperand_Success; -} - /// Sometimes (i.e. load/stores) the operand may be followed immediately by /// either this. /// ::= '(', register, ')' Index: lib/Target/Mips/Disassembler/MipsDisassembler.cpp =================================================================== --- lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -538,6 +538,9 @@ uint64_t Address, const void *Decoder); +static DecodeStatus DecodeMovePOperands(MCInst &Inst, unsigned Insn, + uint64_t Address, const void *Decoder); + namespace llvm { Target &getTheMipselTarget(); @@ -2450,6 +2453,32 @@ return MCDisassembler::Success; } +static DecodeStatus DecodeMovePOperands(MCInst &Inst, unsigned Insn, + uint64_t Address, + const void *Decoder) { + unsigned RegPair = fieldFromInstruction(Insn, 7, 3); + if (DecodeMovePRegPair(Inst, RegPair, Address, Decoder) == + MCDisassembler::Fail) + return MCDisassembler::Fail; + + unsigned RegRs; + if (static_cast(Decoder)->hasMips32r6()) + RegRs = fieldFromInstruction(Insn, 0, 2) | + (fieldFromInstruction(Insn, 3, 1) << 2); + else + RegRs = fieldFromInstruction(Insn, 1, 3); + if (DecodeGPRMM16MovePRegisterClass(Inst, RegRs, Address, Decoder) == + MCDisassembler::Fail) + return MCDisassembler::Fail; + + unsigned RegRt = fieldFromInstruction(Insn, 4, 3); + if (DecodeGPRMM16MovePRegisterClass(Inst, RegRt, Address, Decoder) == + MCDisassembler::Fail) + return MCDisassembler::Fail; + + return MCDisassembler::Success; +} + static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned RegPair, uint64_t Address, const void *Decoder) { switch (RegPair) { Index: lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp =================================================================== --- lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -213,6 +213,12 @@ TmpInst.setOpcode (NewOpcode); Binary = getBinaryCodeForInstr(TmpInst, Fixups, STI); } + + if (((MI.getOpcode() == Mips::MOVEP_MM) || + (MI.getOpcode() == Mips::MOVEP_MMR6))) { + unsigned RegPair = getMovePRegPairOpValue(MI, 0, Fixups, STI); + Binary = (Binary & 0xFFFFFC7F) | (RegPair << 7); + } } const MCInstrDesc &Desc = MCII.get(TmpInst.getOpcode()); Index: lib/Target/Mips/MicroMips32r6InstrInfo.td =================================================================== --- lib/Target/Mips/MicroMips32r6InstrInfo.td +++ lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -1101,7 +1101,9 @@ class LI16_MMR6_DESC : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, MMR6Arch<"li16">, IsAsCheapAsAMove; class MOVE16_MMR6_DESC : MoveMM16<"move16", GPR32Opnd>, MMR6Arch<"move16">; -class MOVEP_MMR6_DESC : MovePMM16<"movep", GPRMM16OpndMoveP>, MMR6Arch<"movep">; +class MOVEP_MMR6_DESC : MovePMM16<"movep", GPRMM16OpndMovePPairFirst, + GPRMM16OpndMovePPairSecond, GPRMM16OpndMoveP>, + MMR6Arch<"movep">; class SDBBP16_MMR6_DESC : BrkSdbbp16MM<"sdbbp16", II_SDBBP>, MMR6Arch<"sdbbp16">; class SUBU16_MMR6_DESC : ArithRMM16<"subu16", GPRMM16Opnd, 0, II_SUBU, sub>, MMR6Arch<"subu16"> { Index: lib/Target/Mips/MicroMipsInstrInfo.td =================================================================== --- lib/Target/Mips/MicroMipsInstrInfo.td +++ lib/Target/Mips/MicroMipsInstrInfo.td @@ -231,27 +231,14 @@ bit mayStore = 1; } -/// A register pair used by movep instruction. -def MovePRegPairAsmOperand : AsmOperandClass { - let Name = "MovePRegPair"; - let ParserMethod = "parseMovePRegPair"; - let PredicateMethod = "isMovePRegPair"; -} - -def movep_regpair : Operand { - let EncoderMethod = "getMovePRegPairOpValue"; - let ParserMatchClass = MovePRegPairAsmOperand; - let PrintMethod = "printRegisterList"; - let DecoderMethod = "DecodeMovePRegPair"; - let MIOperandInfo = (ops ptr_rc, ptr_rc); -} - -class MovePMM16 : -MicroMipsInst16<(outs movep_regpair:$dst_regs), (ins RO:$rs, RO:$rt), - !strconcat(opstr, "\t$dst_regs, $rs, $rt"), [], +class MovePMM16 : +MicroMipsInst16<(outs RO1:$rd1, RO2:$rd2), (ins RO3:$rs, RO3:$rt), + !strconcat(opstr, "\t$rd1, $rd2, $rs, $rt"), [], NoItinerary, FrmR> { let isReMaterializable = 1; let isMoveReg = 1; + let DecoderMethod = "DecodeMovePOperands"; } class StorePairMM @@ -682,8 +669,9 @@ MFHILO_FM_MM16<0x12>, ISA_MICROMIPS32_NOT_MIPS32R6; def MOVE16_MM : MoveMM16<"move", GPR32Opnd>, MOVE_FM_MM16<0x03>, ISA_MICROMIPS32_NOT_MIPS32R6; -def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMoveP>, MOVEP_FM_MM16, - ISA_MICROMIPS32_NOT_MIPS32R6; +def MOVEP_MM : MovePMM16<"movep", GPRMM16OpndMovePPairFirst, + GPRMM16OpndMovePPairSecond, GPRMM16OpndMoveP>, + MOVEP_FM_MM16, ISA_MICROMIPS32_NOT_MIPS32R6; def LI16_MM : LoadImmMM16<"li16", li16_imm, GPRMM16Opnd>, LI_FM_MM16, IsAsCheapAsAMove, ISA_MICROMIPS32_NOT_MIPS32R6; def JALR16_MM : JumpLinkRegMM16<"jalr", GPR32Opnd>, JALR_FM_MM16<0x0e>, Index: lib/Target/Mips/MipsRegisterBankInfo.cpp =================================================================== --- lib/Target/Mips/MipsRegisterBankInfo.cpp +++ lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -57,7 +57,10 @@ switch (RC.getID()) { case Mips::GPR32RegClassID: case Mips::CPU16Regs_and_GPRMM16ZeroRegClassID: + case Mips::GPRMM16MovePPairFirstRegClassID: + case Mips::CPU16Regs_and_GPRMM16MovePPairSecondRegClassID: case Mips::GPRMM16MoveP_and_CPU16Regs_and_GPRMM16ZeroRegClassID: + case Mips::GPRMM16MovePPairFirst_and_GPRMM16MovePPairSecondRegClassID: case Mips::SP32RegClassID: return getRegBank(Mips::GPRBRegBankID); default: Index: lib/Target/Mips/MipsRegisterInfo.td =================================================================== --- lib/Target/Mips/MipsRegisterInfo.td +++ lib/Target/Mips/MipsRegisterInfo.td @@ -335,6 +335,16 @@ // Callee save S0, S2, S3, S4)>; +def GPRMM16MovePPairFirst : RegisterClass<"Mips", [i32], 32, (add + // Arguments + A0, A1, A2)>; + +def GPRMM16MovePPairSecond : RegisterClass<"Mips", [i32], 32, (add + // Arguments + A1, A2, A3, + // Callee save + S5, S6)>; + def GPR64 : RegisterClass<"Mips", [i64], 64, (add // Reserved ZERO_64, AT_64, @@ -522,6 +532,16 @@ let PredicateMethod = "isMM16AsmRegMoveP"; } +def GPRMM16AsmOperandMovePPairFirst : MipsAsmRegOperand { + let Name = "GPRMM16AsmRegMovePPairFirst"; + let PredicateMethod = "isMM16AsmRegMovePPairFirst"; +} + +def GPRMM16AsmOperandMovePPairSecond : MipsAsmRegOperand { + let Name = "GPRMM16AsmRegMovePPairSecond"; + let PredicateMethod = "isMM16AsmRegMovePPairSecond"; +} + def ACC64DSPAsmOperand : MipsAsmRegOperand { let Name = "ACC64DSPAsmReg"; let PredicateMethod = "isACCAsmReg"; @@ -613,6 +633,14 @@ let EncoderMethod = "getMovePRegSingleOpValue"; } +def GPRMM16OpndMovePPairFirst : RegisterOperand { + let ParserMatchClass = GPRMM16AsmOperandMovePPairFirst; +} + +def GPRMM16OpndMovePPairSecond : RegisterOperand { + let ParserMatchClass = GPRMM16AsmOperandMovePPairSecond; +} + def GPR64Opnd : RegisterOperand { let ParserMatchClass = GPR64AsmOperand; }