diff options
Diffstat (limited to 'lib/Target/X86/AsmParser/X86AsmParser.cpp')
-rw-r--r-- | lib/Target/X86/AsmParser/X86AsmParser.cpp | 366 |
1 files changed, 227 insertions, 139 deletions
diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index 4d8ffac1a82bb..4e0ad8bfe1f12 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -11,7 +11,6 @@ #include "X86AsmInstrumentation.h" #include "X86AsmParserCommon.h" #include "X86Operand.h" -#include "llvm/ADT/APFloat.h" #include "llvm/ADT/STLExtras.h" #include "llvm/ADT/SmallString.h" #include "llvm/ADT/SmallVector.h" @@ -24,12 +23,12 @@ #include "llvm/MC/MCParser/MCAsmLexer.h" #include "llvm/MC/MCParser/MCAsmParser.h" #include "llvm/MC/MCParser/MCParsedAsmOperand.h" +#include "llvm/MC/MCParser/MCTargetAsmParser.h" #include "llvm/MC/MCRegisterInfo.h" #include "llvm/MC/MCSection.h" #include "llvm/MC/MCStreamer.h" #include "llvm/MC/MCSubtargetInfo.h" #include "llvm/MC/MCSymbol.h" -#include "llvm/MC/MCTargetAsmParser.h" #include "llvm/Support/SourceMgr.h" #include "llvm/Support/TargetRegistry.h" #include "llvm/Support/raw_ostream.h" @@ -683,9 +682,14 @@ private: std::unique_ptr<X86Operand> DefaultMemSIOperand(SMLoc Loc); std::unique_ptr<X86Operand> DefaultMemDIOperand(SMLoc Loc); - void AddDefaultSrcDestOperands( - OperandVector& Operands, std::unique_ptr<llvm::MCParsedAsmOperand> &&Src, - std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst); + bool IsSIReg(unsigned Reg); + unsigned GetSIDIForRegClass(unsigned RegClassID, unsigned Reg, bool IsSIReg); + void + AddDefaultSrcDestOperands(OperandVector &Operands, + std::unique_ptr<llvm::MCParsedAsmOperand> &&Src, + std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst); + bool VerifyAndAdjustOperands(OperandVector &OrigOperands, + OperandVector &FinalOperands); std::unique_ptr<X86Operand> ParseOperand(); std::unique_ptr<X86Operand> ParseATTOperand(); std::unique_ptr<X86Operand> ParseIntelOperand(); @@ -747,11 +751,6 @@ private: bool OmitRegisterFromClobberLists(unsigned RegNo) override; - /// doSrcDstMatch - Returns true if operands are matching in their - /// word size (%si and %di, %esi and %edi, etc.). Order depends on - /// the parsing mode (Intel vs. AT&T). - bool doSrcDstMatch(X86Operand &Op1, X86Operand &Op2); - /// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z}) /// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required. /// \return \c true if no parsing errors occurred, \c false otherwise. @@ -867,27 +866,6 @@ static bool CheckBaseRegAndIndexReg(unsigned BaseReg, unsigned IndexReg, return false; } -bool X86AsmParser::doSrcDstMatch(X86Operand &Op1, X86Operand &Op2) -{ - // Return true and let a normal complaint about bogus operands happen. - if (!Op1.isMem() || !Op2.isMem()) - return true; - - // Actually these might be the other way round if Intel syntax is - // being used. It doesn't matter. - unsigned diReg = Op1.Mem.BaseReg; - unsigned siReg = Op2.Mem.BaseReg; - - if (X86MCRegisterClasses[X86::GR16RegClassID].contains(siReg)) - return X86MCRegisterClasses[X86::GR16RegClassID].contains(diReg); - if (X86MCRegisterClasses[X86::GR32RegClassID].contains(siReg)) - return X86MCRegisterClasses[X86::GR32RegClassID].contains(diReg); - if (X86MCRegisterClasses[X86::GR64RegClassID].contains(siReg)) - return X86MCRegisterClasses[X86::GR64RegClassID].contains(diReg); - // Again, return true and let another error happen. - return true; -} - bool X86AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) { MCAsmParser &Parser = getParser(); @@ -929,10 +907,16 @@ bool X86AsmParser::ParseRegister(unsigned &RegNo, if (RegNo == X86::RIZ || X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo) || X86II::isX86_64NonExtLowByteReg(RegNo) || - X86II::isX86_64ExtendedReg(RegNo)) + X86II::isX86_64ExtendedReg(RegNo) || + X86II::is32ExtendedReg(RegNo)) return Error(StartLoc, "register %" + Tok.getString() + " is only available in 64-bit mode", SMRange(StartLoc, EndLoc)); + } else if (!getSTI().getFeatureBits()[X86::FeatureAVX512]) { + if (X86II::is32ExtendedReg(RegNo)) + return Error(StartLoc, "register %" + + Tok.getString() + " is only available with AVX512", + SMRange(StartLoc, EndLoc)); } // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens. @@ -1025,6 +1009,33 @@ std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) { Loc, Loc, 0); } +bool X86AsmParser::IsSIReg(unsigned Reg) { + switch (Reg) { + default: llvm_unreachable("Only (R|E)SI and (R|E)DI are expected!"); + case X86::RSI: + case X86::ESI: + case X86::SI: + return true; + case X86::RDI: + case X86::EDI: + case X86::DI: + return false; + } +} + +unsigned X86AsmParser::GetSIDIForRegClass(unsigned RegClassID, unsigned Reg, + bool IsSIReg) { + switch (RegClassID) { + default: llvm_unreachable("Unexpected register class"); + case X86::GR64RegClassID: + return IsSIReg ? X86::RSI : X86::RDI; + case X86::GR32RegClassID: + return IsSIReg ? X86::ESI : X86::EDI; + case X86::GR16RegClassID: + return IsSIReg ? X86::SI : X86::DI; + } +} + void X86AsmParser::AddDefaultSrcDestOperands( OperandVector& Operands, std::unique_ptr<llvm::MCParsedAsmOperand> &&Src, std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst) { @@ -1038,6 +1049,88 @@ void X86AsmParser::AddDefaultSrcDestOperands( } } +bool X86AsmParser::VerifyAndAdjustOperands(OperandVector &OrigOperands, + OperandVector &FinalOperands) { + + if (OrigOperands.size() > 1) { + // Check if sizes match, OrigOperands also contains the instruction name + assert(OrigOperands.size() == FinalOperands.size() + 1 && + "Operand size mismatch"); + + SmallVector<std::pair<SMLoc, std::string>, 2> Warnings; + // Verify types match + int RegClassID = -1; + for (unsigned int i = 0; i < FinalOperands.size(); ++i) { + X86Operand &OrigOp = static_cast<X86Operand &>(*OrigOperands[i + 1]); + X86Operand &FinalOp = static_cast<X86Operand &>(*FinalOperands[i]); + + if (FinalOp.isReg() && + (!OrigOp.isReg() || FinalOp.getReg() != OrigOp.getReg())) + // Return false and let a normal complaint about bogus operands happen + return false; + + if (FinalOp.isMem()) { + + if (!OrigOp.isMem()) + // Return false and let a normal complaint about bogus operands happen + return false; + + unsigned OrigReg = OrigOp.Mem.BaseReg; + unsigned FinalReg = FinalOp.Mem.BaseReg; + + // If we've already encounterd a register class, make sure all register + // bases are of the same register class + if (RegClassID != -1 && + !X86MCRegisterClasses[RegClassID].contains(OrigReg)) { + return Error(OrigOp.getStartLoc(), + "mismatching source and destination index registers"); + } + + if (X86MCRegisterClasses[X86::GR64RegClassID].contains(OrigReg)) + RegClassID = X86::GR64RegClassID; + else if (X86MCRegisterClasses[X86::GR32RegClassID].contains(OrigReg)) + RegClassID = X86::GR32RegClassID; + else if (X86MCRegisterClasses[X86::GR16RegClassID].contains(OrigReg)) + RegClassID = X86::GR16RegClassID; + else + // Unexpected register class type + // Return false and let a normal complaint about bogus operands happen + return false; + + bool IsSI = IsSIReg(FinalReg); + FinalReg = GetSIDIForRegClass(RegClassID, FinalReg, IsSI); + + if (FinalReg != OrigReg) { + std::string RegName = IsSI ? "ES:(R|E)SI" : "ES:(R|E)DI"; + Warnings.push_back(std::make_pair( + OrigOp.getStartLoc(), + "memory operand is only for determining the size, " + RegName + + " will be used for the location")); + } + + FinalOp.Mem.Size = OrigOp.Mem.Size; + FinalOp.Mem.SegReg = OrigOp.Mem.SegReg; + FinalOp.Mem.BaseReg = FinalReg; + } + } + + // Produce warnings only if all the operands passed the adjustment - prevent + // legal cases like "movsd (%rax), %xmm0" mistakenly produce warnings + for (auto &WarningMsg : Warnings) { + Warning(WarningMsg.first, WarningMsg.second); + } + + // Remove old operands + for (unsigned int i = 0; i < FinalOperands.size(); ++i) + OrigOperands.pop_back(); + } + // OrigOperands.append(FinalOperands.begin(), FinalOperands.end()); + for (unsigned int i = 0; i < FinalOperands.size(); ++i) + OrigOperands.push_back(std::move(FinalOperands[i])); + + return false; +} + std::unique_ptr<X86Operand> X86AsmParser::ParseOperand() { if (isParsingIntelSyntax()) return ParseIntelOperand(); @@ -1301,7 +1394,7 @@ X86AsmParser::ParseIntelBracExpression(unsigned SegReg, SMLoc Start, return ErrorOperand(BracLoc, "Expected '[' token!"); Parser.Lex(); // Eat '[' - SMLoc StartInBrac = Tok.getLoc(); + SMLoc StartInBrac = Parser.getTok().getLoc(); // Parse [ Symbol + ImmDisp ] and [ BaseReg + Scale*IndexReg + ImmDisp ]. We // may have already parsed an immediate displacement before the bracketed // expression. @@ -1330,7 +1423,10 @@ X86AsmParser::ParseIntelBracExpression(unsigned SegReg, SMLoc Start, // Parse struct field access. Intel requires a dot, but MSVC doesn't. MSVC // will in fact do global lookup the field name inside all global typedefs, // but we don't emulate that. - if (Tok.getString().find('.') != StringRef::npos) { + if ((Parser.getTok().getKind() == AsmToken::Identifier || + Parser.getTok().getKind() == AsmToken::Dot || + Parser.getTok().getKind() == AsmToken::Real) && + Parser.getTok().getString().find('.') != StringRef::npos) { const MCExpr *NewDisp; if (ParseIntelDotOperator(Disp, NewDisp)) return nullptr; @@ -2087,22 +2183,36 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, unsigned ComparisonCode = StringSwitch<unsigned>( PatchedName.slice(CCIdx, PatchedName.size() - 2)) .Case("eq", 0x00) + .Case("eq_oq", 0x00) .Case("lt", 0x01) + .Case("lt_os", 0x01) .Case("le", 0x02) + .Case("le_os", 0x02) .Case("unord", 0x03) + .Case("unord_q", 0x03) .Case("neq", 0x04) + .Case("neq_uq", 0x04) .Case("nlt", 0x05) + .Case("nlt_us", 0x05) .Case("nle", 0x06) + .Case("nle_us", 0x06) .Case("ord", 0x07) + .Case("ord_q", 0x07) /* AVX only from here */ .Case("eq_uq", 0x08) .Case("nge", 0x09) + .Case("nge_us", 0x09) .Case("ngt", 0x0A) + .Case("ngt_us", 0x0A) .Case("false", 0x0B) + .Case("false_oq", 0x0B) .Case("neq_oq", 0x0C) .Case("ge", 0x0D) + .Case("ge_os", 0x0D) .Case("gt", 0x0E) + .Case("gt_os", 0x0E) .Case("true", 0x0F) + .Case("true_uq", 0x0F) .Case("eq_os", 0x10) .Case("lt_oq", 0x11) .Case("le_oq", 0x12) @@ -2196,6 +2306,7 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, Name == "repne" || Name == "repnz" || Name == "rex64" || Name == "data16"; + bool CurlyAsEndOfStatement = false; // This does the actual operand parsing. Don't parse any more if we have a // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we // just want to parse the "lock" as the first instruction and the "incl" as @@ -2223,7 +2334,12 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, break; } - if (getLexer().isNot(AsmToken::EndOfStatement)) + // In MS inline asm curly braces mark the begining/end of a block, therefore + // they should be interepreted as end of statement + CurlyAsEndOfStatement = + isParsingIntelSyntax() && isParsingInlineAsm() && + (getLexer().is(AsmToken::LCurly) || getLexer().is(AsmToken::RCurly)); + if (getLexer().isNot(AsmToken::EndOfStatement) && !CurlyAsEndOfStatement) return ErrorAndEatStatement(getLexer().getLoc(), "unexpected token in argument list"); } @@ -2232,6 +2348,10 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, if (getLexer().is(AsmToken::EndOfStatement) || (isPrefix && getLexer().is(AsmToken::Slash))) Parser.Lex(); + else if (CurlyAsEndOfStatement) + // Add an actual EndOfStatement before the curly brace + Info.AsmRewrites->emplace_back(AOK_EndOfStatement, + getLexer().getTok().getLoc(), 0); // This is for gas compatibility and cannot be done in td. // Adding "p" for some floating point with no argument. @@ -2247,10 +2367,11 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, static_cast<X86Operand &>(*Operands[0]).setTokenValue(Repl); } - // This is a terrible hack to handle "out[bwl]? %al, (%dx)" -> + // This is a terrible hack to handle "out[s]?[bwl]? %al, (%dx)" -> // "outb %al, %dx". Out doesn't take a memory form, but this is a widely // documented form in various unofficial manuals, so a lot of code uses it. - if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") && + if ((Name == "outb" || Name == "outsb" || Name == "outw" || Name == "outsw" || + Name == "outl" || Name == "outsl" || Name == "out" || Name == "outs") && Operands.size() == 3) { X86Operand &Op = (X86Operand &)*Operands.back(); if (Op.isMem() && Op.Mem.SegReg == 0 && @@ -2261,8 +2382,9 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, Operands.back() = X86Operand::CreateReg(Op.Mem.BaseReg, Loc, Loc); } } - // Same hack for "in[bwl]? (%dx), %al" -> "inb %dx, %al". - if ((Name == "inb" || Name == "inw" || Name == "inl" || Name == "in") && + // Same hack for "in[s]?[bwl]? (%dx), %al" -> "inb %dx, %al". + if ((Name == "inb" || Name == "insb" || Name == "inw" || Name == "insw" || + Name == "inl" || Name == "insl" || Name == "in" || Name == "ins") && Operands.size() == 3) { X86Operand &Op = (X86Operand &)*Operands[1]; if (Op.isMem() && Op.Mem.SegReg == 0 && @@ -2274,84 +2396,92 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } } + SmallVector<std::unique_ptr<MCParsedAsmOperand>, 2> TmpOperands; + bool HadVerifyError = false; + // Append default arguments to "ins[bwld]" - if (Name.startswith("ins") && Operands.size() == 1 && - (Name == "insb" || Name == "insw" || Name == "insl" || Name == "insd")) { - AddDefaultSrcDestOperands(Operands, + if (Name.startswith("ins") && + (Operands.size() == 1 || Operands.size() == 3) && + (Name == "insb" || Name == "insw" || Name == "insl" || Name == "insd" || + Name == "ins")) { + + AddDefaultSrcDestOperands(TmpOperands, X86Operand::CreateReg(X86::DX, NameLoc, NameLoc), DefaultMemDIOperand(NameLoc)); + HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands); } // Append default arguments to "outs[bwld]" - if (Name.startswith("outs") && Operands.size() == 1 && + if (Name.startswith("outs") && + (Operands.size() == 1 || Operands.size() == 3) && (Name == "outsb" || Name == "outsw" || Name == "outsl" || - Name == "outsd" )) { - AddDefaultSrcDestOperands(Operands, - DefaultMemSIOperand(NameLoc), + Name == "outsd" || Name == "outs")) { + AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc), X86Operand::CreateReg(X86::DX, NameLoc, NameLoc)); + HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands); } // Transform "lods[bwlq]" into "lods[bwlq] ($SIREG)" for appropriate // values of $SIREG according to the mode. It would be nice if this // could be achieved with InstAlias in the tables. - if (Name.startswith("lods") && Operands.size() == 1 && + if (Name.startswith("lods") && + (Operands.size() == 1 || Operands.size() == 2) && (Name == "lods" || Name == "lodsb" || Name == "lodsw" || - Name == "lodsl" || Name == "lodsd" || Name == "lodsq")) - Operands.push_back(DefaultMemSIOperand(NameLoc)); + Name == "lodsl" || Name == "lodsd" || Name == "lodsq")) { + TmpOperands.push_back(DefaultMemSIOperand(NameLoc)); + HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands); + } // Transform "stos[bwlq]" into "stos[bwlq] ($DIREG)" for appropriate // values of $DIREG according to the mode. It would be nice if this // could be achieved with InstAlias in the tables. - if (Name.startswith("stos") && Operands.size() == 1 && + if (Name.startswith("stos") && + (Operands.size() == 1 || Operands.size() == 2) && (Name == "stos" || Name == "stosb" || Name == "stosw" || - Name == "stosl" || Name == "stosd" || Name == "stosq")) - Operands.push_back(DefaultMemDIOperand(NameLoc)); + Name == "stosl" || Name == "stosd" || Name == "stosq")) { + TmpOperands.push_back(DefaultMemDIOperand(NameLoc)); + HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands); + } // Transform "scas[bwlq]" into "scas[bwlq] ($DIREG)" for appropriate // values of $DIREG according to the mode. It would be nice if this // could be achieved with InstAlias in the tables. - if (Name.startswith("scas") && Operands.size() == 1 && + if (Name.startswith("scas") && + (Operands.size() == 1 || Operands.size() == 2) && (Name == "scas" || Name == "scasb" || Name == "scasw" || - Name == "scasl" || Name == "scasd" || Name == "scasq")) - Operands.push_back(DefaultMemDIOperand(NameLoc)); + Name == "scasl" || Name == "scasd" || Name == "scasq")) { + TmpOperands.push_back(DefaultMemDIOperand(NameLoc)); + HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands); + } // Add default SI and DI operands to "cmps[bwlq]". if (Name.startswith("cmps") && + (Operands.size() == 1 || Operands.size() == 3) && (Name == "cmps" || Name == "cmpsb" || Name == "cmpsw" || Name == "cmpsl" || Name == "cmpsd" || Name == "cmpsq")) { - if (Operands.size() == 1) { - AddDefaultSrcDestOperands(Operands, - DefaultMemDIOperand(NameLoc), - DefaultMemSIOperand(NameLoc)); - } else if (Operands.size() == 3) { - X86Operand &Op = (X86Operand &)*Operands[1]; - X86Operand &Op2 = (X86Operand &)*Operands[2]; - if (!doSrcDstMatch(Op, Op2)) - return Error(Op.getStartLoc(), - "mismatching source and destination index registers"); - } + AddDefaultSrcDestOperands(TmpOperands, DefaultMemDIOperand(NameLoc), + DefaultMemSIOperand(NameLoc)); + HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands); } // Add default SI and DI operands to "movs[bwlq]". - if ((Name.startswith("movs") && - (Name == "movs" || Name == "movsb" || Name == "movsw" || - Name == "movsl" || Name == "movsd" || Name == "movsq")) || - (Name.startswith("smov") && - (Name == "smov" || Name == "smovb" || Name == "smovw" || - Name == "smovl" || Name == "smovd" || Name == "smovq"))) { - if (Operands.size() == 1) { - if (Name == "movsd") - Operands.back() = X86Operand::CreateToken("movsl", NameLoc); - AddDefaultSrcDestOperands(Operands, - DefaultMemSIOperand(NameLoc), - DefaultMemDIOperand(NameLoc)); - } else if (Operands.size() == 3) { - X86Operand &Op = (X86Operand &)*Operands[1]; - X86Operand &Op2 = (X86Operand &)*Operands[2]; - if (!doSrcDstMatch(Op, Op2)) - return Error(Op.getStartLoc(), - "mismatching source and destination index registers"); - } + if (((Name.startswith("movs") && + (Name == "movs" || Name == "movsb" || Name == "movsw" || + Name == "movsl" || Name == "movsd" || Name == "movsq")) || + (Name.startswith("smov") && + (Name == "smov" || Name == "smovb" || Name == "smovw" || + Name == "smovl" || Name == "smovd" || Name == "smovq"))) && + (Operands.size() == 1 || Operands.size() == 3)) { + if (Name == "movsd" && Operands.size() == 1) + Operands.back() = X86Operand::CreateToken("movsl", NameLoc); + AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc), + DefaultMemDIOperand(NameLoc)); + HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands); + } + + // Check if we encountered an error for one the string insturctions + if (HadVerifyError) { + return HadVerifyError; } // FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>. Canonicalize to @@ -2387,64 +2517,22 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name, } } + // Transforms "xlat mem8" into "xlatb" + if ((Name == "xlat" || Name == "xlatb") && Operands.size() == 2) { + X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]); + if (Op1.isMem8()) { + Warning(Op1.getStartLoc(), "memory operand is only for determining the " + "size, (R|E)BX will be used for the location"); + Operands.pop_back(); + static_cast<X86Operand &>(*Operands[0]).setTokenValue("xlatb"); + } + } + return false; } bool X86AsmParser::processInstruction(MCInst &Inst, const OperandVector &Ops) { - switch (Inst.getOpcode()) { - default: return false; - case X86::VMOVZPQILo2PQIrr: - case X86::VMOVAPDrr: - case X86::VMOVAPDYrr: - case X86::VMOVAPSrr: - case X86::VMOVAPSYrr: - case X86::VMOVDQArr: - case X86::VMOVDQAYrr: - case X86::VMOVDQUrr: - case X86::VMOVDQUYrr: - case X86::VMOVUPDrr: - case X86::VMOVUPDYrr: - case X86::VMOVUPSrr: - case X86::VMOVUPSYrr: { - if (X86II::isX86_64ExtendedReg(Inst.getOperand(0).getReg()) || - !X86II::isX86_64ExtendedReg(Inst.getOperand(1).getReg())) - return false; - - unsigned NewOpc; - switch (Inst.getOpcode()) { - default: llvm_unreachable("Invalid opcode"); - case X86::VMOVZPQILo2PQIrr: NewOpc = X86::VMOVPQI2QIrr; break; - case X86::VMOVAPDrr: NewOpc = X86::VMOVAPDrr_REV; break; - case X86::VMOVAPDYrr: NewOpc = X86::VMOVAPDYrr_REV; break; - case X86::VMOVAPSrr: NewOpc = X86::VMOVAPSrr_REV; break; - case X86::VMOVAPSYrr: NewOpc = X86::VMOVAPSYrr_REV; break; - case X86::VMOVDQArr: NewOpc = X86::VMOVDQArr_REV; break; - case X86::VMOVDQAYrr: NewOpc = X86::VMOVDQAYrr_REV; break; - case X86::VMOVDQUrr: NewOpc = X86::VMOVDQUrr_REV; break; - case X86::VMOVDQUYrr: NewOpc = X86::VMOVDQUYrr_REV; break; - case X86::VMOVUPDrr: NewOpc = X86::VMOVUPDrr_REV; break; - case X86::VMOVUPDYrr: NewOpc = X86::VMOVUPDYrr_REV; break; - case X86::VMOVUPSrr: NewOpc = X86::VMOVUPSrr_REV; break; - case X86::VMOVUPSYrr: NewOpc = X86::VMOVUPSYrr_REV; break; - } - Inst.setOpcode(NewOpc); - return true; - } - case X86::VMOVSDrr: - case X86::VMOVSSrr: { - if (X86II::isX86_64ExtendedReg(Inst.getOperand(0).getReg()) || - !X86II::isX86_64ExtendedReg(Inst.getOperand(2).getReg())) - return false; - unsigned NewOpc; - switch (Inst.getOpcode()) { - default: llvm_unreachable("Invalid opcode"); - case X86::VMOVSDrr: NewOpc = X86::VMOVSDrr_REV; break; - case X86::VMOVSSrr: NewOpc = X86::VMOVSSrr_REV; break; - } - Inst.setOpcode(NewOpc); - return true; - } - } + return false; } static const char *getSubtargetFeatureName(uint64_t Val); |