[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
This commit is contained in:
Simon Atanasyan 2018-09-19 18:46:21 +00:00
parent 241c33bca7
commit 852dd83be8
7 changed files with 117 additions and 134 deletions

View File

@ -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<MipsOperand> CreateToken(StringRef Str, SMLoc S,
MipsAsmParser &Parser) {
auto Op = llvm::make_unique<MipsOperand>(k_Token, Parser);
@ -1593,18 +1545,6 @@ public:
return Op;
}
static std::unique_ptr<MipsOperand> CreateRegPair(const MipsOperand &MOP,
SMLoc S, SMLoc E,
MipsAsmParser &Parser) {
auto Op = llvm::make_unique<MipsOperand>(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<std::unique_ptr<MCParsedAsmOperand>, 8> TmpOperands;
SmallVector<unsigned, 10> 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<MipsOperand &>(*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<MipsOperand &>(*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, ')'

View File

@ -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<const MipsDisassembler*>(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) {

View File

@ -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());

View File

@ -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"> {

View File

@ -231,27 +231,14 @@ class StoreLeftRightMM<string opstr, SDNode OpNode, RegisterOperand RO,
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<i32> {
let EncoderMethod = "getMovePRegPairOpValue";
let ParserMatchClass = MovePRegPairAsmOperand;
let PrintMethod = "printRegisterList";
let DecoderMethod = "DecodeMovePRegPair";
let MIOperandInfo = (ops ptr_rc, ptr_rc);
}
class MovePMM16<string opstr, RegisterOperand RO> :
MicroMipsInst16<(outs movep_regpair:$dst_regs), (ins RO:$rs, RO:$rt),
!strconcat(opstr, "\t$dst_regs, $rs, $rt"), [],
class MovePMM16<string opstr, RegisterOperand RO1, RegisterOperand RO2,
RegisterOperand RO3> :
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<string opstr, ComplexPattern Addr = addr>
@ -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>,

View File

@ -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:

View File

@ -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<GPRMM16MoveP> {
let EncoderMethod = "getMovePRegSingleOpValue";
}
def GPRMM16OpndMovePPairFirst : RegisterOperand<GPRMM16MovePPairFirst> {
let ParserMatchClass = GPRMM16AsmOperandMovePPairFirst;
}
def GPRMM16OpndMovePPairSecond : RegisterOperand<GPRMM16MovePPairSecond> {
let ParserMatchClass = GPRMM16AsmOperandMovePPairSecond;
}
def GPR64Opnd : RegisterOperand<GPR64> {
let ParserMatchClass = GPR64AsmOperand;
}