forked from OSchip/llvm-project
[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:
parent
241c33bca7
commit
852dd83be8
|
@ -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, ')'
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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"> {
|
||||
|
|
|
@ -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>,
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue