From 852dd83be8b7586036877065e690f5bcb564ea86 Mon Sep 17 00:00:00 2001 From: Simon Atanasyan Date: Wed, 19 Sep 2018 18:46:21 +0000 Subject: [PATCH] [mips][microMIPS] Fix the definition of MOVEP instruction The patch fixes definition of MOVEP instruction. Two registers are used instead of register pairs. This is necessary as machine verifier cannot handle register pairs. Patch by Milena Vujosevic Janicic. Differential revision: https://reviews.llvm.org/D52035 llvm-svn: 342571 --- .../Target/Mips/AsmParser/MipsAsmParser.cpp | 153 +++++------------- .../Mips/Disassembler/MipsDisassembler.cpp | 29 ++++ .../Mips/MCTargetDesc/MipsMCCodeEmitter.cpp | 6 + .../lib/Target/Mips/MicroMips32r6InstrInfo.td | 4 +- llvm/lib/Target/Mips/MicroMipsInstrInfo.td | 28 +--- llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp | 3 + llvm/lib/Target/Mips/MipsRegisterInfo.td | 28 ++++ 7 files changed, 117 insertions(+), 134 deletions(-) diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp index ae70fdd37c12..2e70d35fc4af 100644 --- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp +++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp @@ -195,7 +195,6 @@ class MipsAsmParser : public MCTargetAsmParser { 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 @@ private: 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 @@ public: delete RegList.List; case k_RegisterIndex: case k_Token: - case k_RegPair: break; } } @@ -1038,6 +1035,17 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: 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 @@ public: (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 @@ public: OS << Reg << " "; OS << ">"; break; - case k_RegPair: - OS << "RegPair<" << RegIdx.Index << "," << RegIdx.Index + 1 << ">"; - break; } } @@ -2288,6 +2238,22 @@ bool MipsAsmParser::processInstruction(MCInst &Inst, SMLoc IDLoc, 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 @@ MipsAsmParser::parseRegisterList(OperandVector &Operands) { 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, ')' diff --git a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp index b94afb9520e3..27b27ff1e1e2 100644 --- a/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp +++ b/llvm/lib/Target/Mips/Disassembler/MipsDisassembler.cpp @@ -538,6 +538,9 @@ static DecodeStatus DecodeMovePRegPair(MCInst &Inst, unsigned RegPair, 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 @@ static DecodeStatus DecodeRegListOperand16(MCInst &Inst, unsigned Insn, 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) { diff --git a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp index cd34b0ab70b4..8e880b635c15 100644 --- a/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp +++ b/llvm/lib/Target/Mips/MCTargetDesc/MipsMCCodeEmitter.cpp @@ -213,6 +213,12 @@ encodeInstruction(const MCInst &MI, raw_ostream &OS, 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()); diff --git a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td index 6b0aa7756eab..b5896060a710 100644 --- a/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMips32r6InstrInfo.td @@ -1101,7 +1101,9 @@ class BREAK16_MMR6_DESC : BrkSdbbp16MM<"break16", II_BREAK>, MMR6Arch<"break16"> 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"> { diff --git a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td index 9f914bb9e870..174a05ea7af6 100644 --- a/llvm/lib/Target/Mips/MicroMipsInstrInfo.td +++ b/llvm/lib/Target/Mips/MicroMipsInstrInfo.td @@ -231,27 +231,14 @@ class StoreLeftRightMM { - 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 @@ def MFLO16_MM : MoveFromHILOMM<"mflo16", GPR32Opnd, AC0>, 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>, diff --git a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp index 96ca1cdd6432..a0c80048c024 100644 --- a/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp +++ b/llvm/lib/Target/Mips/MipsRegisterBankInfo.cpp @@ -57,7 +57,10 @@ const RegisterBank &MipsRegisterBankInfo::getRegBankFromRegClass( 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: diff --git a/llvm/lib/Target/Mips/MipsRegisterInfo.td b/llvm/lib/Target/Mips/MipsRegisterInfo.td index c85ee20273c0..a943a0ad4094 100644 --- a/llvm/lib/Target/Mips/MipsRegisterInfo.td +++ b/llvm/lib/Target/Mips/MipsRegisterInfo.td @@ -335,6 +335,16 @@ def GPRMM16MoveP : RegisterClass<"Mips", [i32], 32, (add // 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 @@ def GPRMM16AsmOperandMoveP : MipsAsmRegOperand { 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 @@ def GPRMM16OpndMoveP : RegisterOperand { let EncoderMethod = "getMovePRegSingleOpValue"; } +def GPRMM16OpndMovePPairFirst : RegisterOperand { + let ParserMatchClass = GPRMM16AsmOperandMovePPairFirst; +} + +def GPRMM16OpndMovePPairSecond : RegisterOperand { + let ParserMatchClass = GPRMM16AsmOperandMovePPairSecond; +} + def GPR64Opnd : RegisterOperand { let ParserMatchClass = GPR64AsmOperand; }