xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp (revision 6e516c87b6d779911edde7481d8aef165b837a03)
10b57cec5SDimitry Andric //===-- X86AsmParser.cpp - Parse X86 assembly to MCInst instructions ------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric 
90b57cec5SDimitry Andric #include "MCTargetDesc/X86BaseInfo.h"
1006c3fb27SDimitry Andric #include "MCTargetDesc/X86EncodingOptimization.h"
110b57cec5SDimitry Andric #include "MCTargetDesc/X86IntelInstPrinter.h"
120b57cec5SDimitry Andric #include "MCTargetDesc/X86MCExpr.h"
1381ad6265SDimitry Andric #include "MCTargetDesc/X86MCTargetDesc.h"
140b57cec5SDimitry Andric #include "MCTargetDesc/X86TargetStreamer.h"
150b57cec5SDimitry Andric #include "TargetInfo/X86TargetInfo.h"
160b57cec5SDimitry Andric #include "X86AsmParserCommon.h"
170b57cec5SDimitry Andric #include "X86Operand.h"
180b57cec5SDimitry Andric #include "llvm/ADT/STLExtras.h"
190b57cec5SDimitry Andric #include "llvm/ADT/SmallString.h"
200b57cec5SDimitry Andric #include "llvm/ADT/SmallVector.h"
210b57cec5SDimitry Andric #include "llvm/ADT/StringSwitch.h"
220b57cec5SDimitry Andric #include "llvm/ADT/Twine.h"
230b57cec5SDimitry Andric #include "llvm/MC/MCContext.h"
240b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
250b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
260b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
270b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmLexer.h"
280b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCAsmParser.h"
290b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
300b57cec5SDimitry Andric #include "llvm/MC/MCParser/MCTargetAsmParser.h"
310b57cec5SDimitry Andric #include "llvm/MC/MCRegisterInfo.h"
320b57cec5SDimitry Andric #include "llvm/MC/MCSection.h"
330b57cec5SDimitry Andric #include "llvm/MC/MCStreamer.h"
340b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
350b57cec5SDimitry Andric #include "llvm/MC/MCSymbol.h"
36349cc55cSDimitry Andric #include "llvm/MC/TargetRegistry.h"
375ffd83dbSDimitry Andric #include "llvm/Support/CommandLine.h"
38e8d8bef9SDimitry Andric #include "llvm/Support/Compiler.h"
390b57cec5SDimitry Andric #include "llvm/Support/SourceMgr.h"
400b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
410b57cec5SDimitry Andric #include <algorithm>
420b57cec5SDimitry Andric #include <memory>
430b57cec5SDimitry Andric 
440b57cec5SDimitry Andric using namespace llvm;
450b57cec5SDimitry Andric 
465ffd83dbSDimitry Andric static cl::opt<bool> LVIInlineAsmHardening(
475ffd83dbSDimitry Andric     "x86-experimental-lvi-inline-asm-hardening",
485ffd83dbSDimitry Andric     cl::desc("Harden inline assembly code that may be vulnerable to Load Value"
495ffd83dbSDimitry Andric              " Injection (LVI). This feature is experimental."), cl::Hidden);
505ffd83dbSDimitry Andric 
checkScale(unsigned Scale,StringRef & ErrMsg)510b57cec5SDimitry Andric static bool checkScale(unsigned Scale, StringRef &ErrMsg) {
520b57cec5SDimitry Andric   if (Scale != 1 && Scale != 2 && Scale != 4 && Scale != 8) {
530b57cec5SDimitry Andric     ErrMsg = "scale factor in address must be 1, 2, 4 or 8";
540b57cec5SDimitry Andric     return true;
550b57cec5SDimitry Andric   }
560b57cec5SDimitry Andric   return false;
570b57cec5SDimitry Andric }
580b57cec5SDimitry Andric 
590b57cec5SDimitry Andric namespace {
600b57cec5SDimitry Andric 
610fca6ea1SDimitry Andric // Including the generated SSE2AVX compression tables.
620fca6ea1SDimitry Andric #define GET_X86_SSE2AVX_TABLE
630fca6ea1SDimitry Andric #include "X86GenInstrMapping.inc"
640fca6ea1SDimitry Andric 
650b57cec5SDimitry Andric static const char OpPrecedence[] = {
660b57cec5SDimitry Andric     0,  // IC_OR
670b57cec5SDimitry Andric     1,  // IC_XOR
680b57cec5SDimitry Andric     2,  // IC_AND
69e8d8bef9SDimitry Andric     4,  // IC_LSHIFT
70e8d8bef9SDimitry Andric     4,  // IC_RSHIFT
71e8d8bef9SDimitry Andric     5,  // IC_PLUS
72e8d8bef9SDimitry Andric     5,  // IC_MINUS
73e8d8bef9SDimitry Andric     6,  // IC_MULTIPLY
74e8d8bef9SDimitry Andric     6,  // IC_DIVIDE
75e8d8bef9SDimitry Andric     6,  // IC_MOD
76e8d8bef9SDimitry Andric     7,  // IC_NOT
77e8d8bef9SDimitry Andric     8,  // IC_NEG
78e8d8bef9SDimitry Andric     9,  // IC_RPAREN
79e8d8bef9SDimitry Andric     10, // IC_LPAREN
800b57cec5SDimitry Andric     0,  // IC_IMM
81e8d8bef9SDimitry Andric     0,  // IC_REGISTER
82e8d8bef9SDimitry Andric     3,  // IC_EQ
83e8d8bef9SDimitry Andric     3,  // IC_NE
84e8d8bef9SDimitry Andric     3,  // IC_LT
85e8d8bef9SDimitry Andric     3,  // IC_LE
86e8d8bef9SDimitry Andric     3,  // IC_GT
87e8d8bef9SDimitry Andric     3   // IC_GE
880b57cec5SDimitry Andric };
890b57cec5SDimitry Andric 
900b57cec5SDimitry Andric class X86AsmParser : public MCTargetAsmParser {
910b57cec5SDimitry Andric   ParseInstructionInfo *InstInfo;
920b57cec5SDimitry Andric   bool Code16GCC;
93e8d8bef9SDimitry Andric   unsigned ForcedDataPrefix = 0;
940b57cec5SDimitry Andric 
950fca6ea1SDimitry Andric   enum OpcodePrefix {
960fca6ea1SDimitry Andric     OpcodePrefix_Default,
970fca6ea1SDimitry Andric     OpcodePrefix_REX,
980fca6ea1SDimitry Andric     OpcodePrefix_REX2,
990fca6ea1SDimitry Andric     OpcodePrefix_VEX,
1000fca6ea1SDimitry Andric     OpcodePrefix_VEX2,
1010fca6ea1SDimitry Andric     OpcodePrefix_VEX3,
1020fca6ea1SDimitry Andric     OpcodePrefix_EVEX,
1030b57cec5SDimitry Andric   };
1040b57cec5SDimitry Andric 
1050fca6ea1SDimitry Andric   OpcodePrefix ForcedOpcodePrefix = OpcodePrefix_Default;
1060b57cec5SDimitry Andric 
107e8d8bef9SDimitry Andric   enum DispEncoding {
108e8d8bef9SDimitry Andric     DispEncoding_Default,
109e8d8bef9SDimitry Andric     DispEncoding_Disp8,
110e8d8bef9SDimitry Andric     DispEncoding_Disp32,
111e8d8bef9SDimitry Andric   };
112e8d8bef9SDimitry Andric 
113e8d8bef9SDimitry Andric   DispEncoding ForcedDispEncoding = DispEncoding_Default;
114e8d8bef9SDimitry Andric 
1155f757f3fSDimitry Andric   // Does this instruction use apx extended register?
1165f757f3fSDimitry Andric   bool UseApxExtendedReg = false;
117647cbc5dSDimitry Andric   // Is this instruction explicitly required not to update flags?
118647cbc5dSDimitry Andric   bool ForcedNoFlag = false;
1195f757f3fSDimitry Andric 
1200b57cec5SDimitry Andric private:
consumeToken()1210b57cec5SDimitry Andric   SMLoc consumeToken() {
1220b57cec5SDimitry Andric     MCAsmParser &Parser = getParser();
1230b57cec5SDimitry Andric     SMLoc Result = Parser.getTok().getLoc();
1240b57cec5SDimitry Andric     Parser.Lex();
1250b57cec5SDimitry Andric     return Result;
1260b57cec5SDimitry Andric   }
1270b57cec5SDimitry Andric 
getTargetStreamer()1280b57cec5SDimitry Andric   X86TargetStreamer &getTargetStreamer() {
1290b57cec5SDimitry Andric     assert(getParser().getStreamer().getTargetStreamer() &&
1300b57cec5SDimitry Andric            "do not have a target streamer");
1310b57cec5SDimitry Andric     MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
1320b57cec5SDimitry Andric     return static_cast<X86TargetStreamer &>(TS);
1330b57cec5SDimitry Andric   }
1340b57cec5SDimitry Andric 
MatchInstruction(const OperandVector & Operands,MCInst & Inst,uint64_t & ErrorInfo,FeatureBitset & MissingFeatures,bool matchingInlineAsm,unsigned VariantID=0)1350b57cec5SDimitry Andric   unsigned MatchInstruction(const OperandVector &Operands, MCInst &Inst,
1360b57cec5SDimitry Andric                             uint64_t &ErrorInfo, FeatureBitset &MissingFeatures,
1370b57cec5SDimitry Andric                             bool matchingInlineAsm, unsigned VariantID = 0) {
1380b57cec5SDimitry Andric     // In Code16GCC mode, match as 32-bit.
1390b57cec5SDimitry Andric     if (Code16GCC)
14081ad6265SDimitry Andric       SwitchMode(X86::Is32Bit);
1410b57cec5SDimitry Andric     unsigned rv = MatchInstructionImpl(Operands, Inst, ErrorInfo,
1420b57cec5SDimitry Andric                                        MissingFeatures, matchingInlineAsm,
1430b57cec5SDimitry Andric                                        VariantID);
1440b57cec5SDimitry Andric     if (Code16GCC)
14581ad6265SDimitry Andric       SwitchMode(X86::Is16Bit);
1460b57cec5SDimitry Andric     return rv;
1470b57cec5SDimitry Andric   }
1480b57cec5SDimitry Andric 
1490b57cec5SDimitry Andric   enum InfixCalculatorTok {
1500b57cec5SDimitry Andric     IC_OR = 0,
1510b57cec5SDimitry Andric     IC_XOR,
1520b57cec5SDimitry Andric     IC_AND,
1530b57cec5SDimitry Andric     IC_LSHIFT,
1540b57cec5SDimitry Andric     IC_RSHIFT,
1550b57cec5SDimitry Andric     IC_PLUS,
1560b57cec5SDimitry Andric     IC_MINUS,
1570b57cec5SDimitry Andric     IC_MULTIPLY,
1580b57cec5SDimitry Andric     IC_DIVIDE,
1590b57cec5SDimitry Andric     IC_MOD,
1600b57cec5SDimitry Andric     IC_NOT,
1610b57cec5SDimitry Andric     IC_NEG,
1620b57cec5SDimitry Andric     IC_RPAREN,
1630b57cec5SDimitry Andric     IC_LPAREN,
1640b57cec5SDimitry Andric     IC_IMM,
165e8d8bef9SDimitry Andric     IC_REGISTER,
166e8d8bef9SDimitry Andric     IC_EQ,
167e8d8bef9SDimitry Andric     IC_NE,
168e8d8bef9SDimitry Andric     IC_LT,
169e8d8bef9SDimitry Andric     IC_LE,
170e8d8bef9SDimitry Andric     IC_GT,
171e8d8bef9SDimitry Andric     IC_GE
1720b57cec5SDimitry Andric   };
1730b57cec5SDimitry Andric 
1740b57cec5SDimitry Andric   enum IntelOperatorKind {
1750b57cec5SDimitry Andric     IOK_INVALID = 0,
1760b57cec5SDimitry Andric     IOK_LENGTH,
1770b57cec5SDimitry Andric     IOK_SIZE,
1780b57cec5SDimitry Andric     IOK_TYPE,
1790b57cec5SDimitry Andric   };
1800b57cec5SDimitry Andric 
181e8d8bef9SDimitry Andric   enum MasmOperatorKind {
182e8d8bef9SDimitry Andric     MOK_INVALID = 0,
183e8d8bef9SDimitry Andric     MOK_LENGTHOF,
184e8d8bef9SDimitry Andric     MOK_SIZEOF,
185e8d8bef9SDimitry Andric     MOK_TYPE,
186e8d8bef9SDimitry Andric   };
187e8d8bef9SDimitry Andric 
1880b57cec5SDimitry Andric   class InfixCalculator {
1890b57cec5SDimitry Andric     typedef std::pair< InfixCalculatorTok, int64_t > ICToken;
1900b57cec5SDimitry Andric     SmallVector<InfixCalculatorTok, 4> InfixOperatorStack;
1910b57cec5SDimitry Andric     SmallVector<ICToken, 4> PostfixStack;
1920b57cec5SDimitry Andric 
isUnaryOperator(InfixCalculatorTok Op) const193e8d8bef9SDimitry Andric     bool isUnaryOperator(InfixCalculatorTok Op) const {
1940b57cec5SDimitry Andric       return Op == IC_NEG || Op == IC_NOT;
1950b57cec5SDimitry Andric     }
1960b57cec5SDimitry Andric 
1970b57cec5SDimitry Andric   public:
popOperand()1980b57cec5SDimitry Andric     int64_t popOperand() {
1990b57cec5SDimitry Andric       assert (!PostfixStack.empty() && "Poped an empty stack!");
2000b57cec5SDimitry Andric       ICToken Op = PostfixStack.pop_back_val();
2010b57cec5SDimitry Andric       if (!(Op.first == IC_IMM || Op.first == IC_REGISTER))
2020b57cec5SDimitry Andric         return -1; // The invalid Scale value will be caught later by checkScale
2030b57cec5SDimitry Andric       return Op.second;
2040b57cec5SDimitry Andric     }
pushOperand(InfixCalculatorTok Op,int64_t Val=0)2050b57cec5SDimitry Andric     void pushOperand(InfixCalculatorTok Op, int64_t Val = 0) {
2060b57cec5SDimitry Andric       assert ((Op == IC_IMM || Op == IC_REGISTER) &&
2070b57cec5SDimitry Andric               "Unexpected operand!");
2080b57cec5SDimitry Andric       PostfixStack.push_back(std::make_pair(Op, Val));
2090b57cec5SDimitry Andric     }
2100b57cec5SDimitry Andric 
popOperator()2110b57cec5SDimitry Andric     void popOperator() { InfixOperatorStack.pop_back(); }
pushOperator(InfixCalculatorTok Op)2120b57cec5SDimitry Andric     void pushOperator(InfixCalculatorTok Op) {
2130b57cec5SDimitry Andric       // Push the new operator if the stack is empty.
2140b57cec5SDimitry Andric       if (InfixOperatorStack.empty()) {
2150b57cec5SDimitry Andric         InfixOperatorStack.push_back(Op);
2160b57cec5SDimitry Andric         return;
2170b57cec5SDimitry Andric       }
2180b57cec5SDimitry Andric 
2190b57cec5SDimitry Andric       // Push the new operator if it has a higher precedence than the operator
2200b57cec5SDimitry Andric       // on the top of the stack or the operator on the top of the stack is a
2210b57cec5SDimitry Andric       // left parentheses.
2220b57cec5SDimitry Andric       unsigned Idx = InfixOperatorStack.size() - 1;
2230b57cec5SDimitry Andric       InfixCalculatorTok StackOp = InfixOperatorStack[Idx];
2240b57cec5SDimitry Andric       if (OpPrecedence[Op] > OpPrecedence[StackOp] || StackOp == IC_LPAREN) {
2250b57cec5SDimitry Andric         InfixOperatorStack.push_back(Op);
2260b57cec5SDimitry Andric         return;
2270b57cec5SDimitry Andric       }
2280b57cec5SDimitry Andric 
2290b57cec5SDimitry Andric       // The operator on the top of the stack has higher precedence than the
2300b57cec5SDimitry Andric       // new operator.
2310b57cec5SDimitry Andric       unsigned ParenCount = 0;
23204eeddc0SDimitry Andric       while (true) {
2330b57cec5SDimitry Andric         // Nothing to process.
2340b57cec5SDimitry Andric         if (InfixOperatorStack.empty())
2350b57cec5SDimitry Andric           break;
2360b57cec5SDimitry Andric 
2370b57cec5SDimitry Andric         Idx = InfixOperatorStack.size() - 1;
2380b57cec5SDimitry Andric         StackOp = InfixOperatorStack[Idx];
2390b57cec5SDimitry Andric         if (!(OpPrecedence[StackOp] >= OpPrecedence[Op] || ParenCount))
2400b57cec5SDimitry Andric           break;
2410b57cec5SDimitry Andric 
2420b57cec5SDimitry Andric         // If we have an even parentheses count and we see a left parentheses,
2430b57cec5SDimitry Andric         // then stop processing.
2440b57cec5SDimitry Andric         if (!ParenCount && StackOp == IC_LPAREN)
2450b57cec5SDimitry Andric           break;
2460b57cec5SDimitry Andric 
2470b57cec5SDimitry Andric         if (StackOp == IC_RPAREN) {
2480b57cec5SDimitry Andric           ++ParenCount;
2490b57cec5SDimitry Andric           InfixOperatorStack.pop_back();
2500b57cec5SDimitry Andric         } else if (StackOp == IC_LPAREN) {
2510b57cec5SDimitry Andric           --ParenCount;
2520b57cec5SDimitry Andric           InfixOperatorStack.pop_back();
2530b57cec5SDimitry Andric         } else {
2540b57cec5SDimitry Andric           InfixOperatorStack.pop_back();
2550b57cec5SDimitry Andric           PostfixStack.push_back(std::make_pair(StackOp, 0));
2560b57cec5SDimitry Andric         }
2570b57cec5SDimitry Andric       }
2580b57cec5SDimitry Andric       // Push the new operator.
2590b57cec5SDimitry Andric       InfixOperatorStack.push_back(Op);
2600b57cec5SDimitry Andric     }
2610b57cec5SDimitry Andric 
execute()2620b57cec5SDimitry Andric     int64_t execute() {
2630b57cec5SDimitry Andric       // Push any remaining operators onto the postfix stack.
2640b57cec5SDimitry Andric       while (!InfixOperatorStack.empty()) {
2650b57cec5SDimitry Andric         InfixCalculatorTok StackOp = InfixOperatorStack.pop_back_val();
2660b57cec5SDimitry Andric         if (StackOp != IC_LPAREN && StackOp != IC_RPAREN)
2670b57cec5SDimitry Andric           PostfixStack.push_back(std::make_pair(StackOp, 0));
2680b57cec5SDimitry Andric       }
2690b57cec5SDimitry Andric 
2700b57cec5SDimitry Andric       if (PostfixStack.empty())
2710b57cec5SDimitry Andric         return 0;
2720b57cec5SDimitry Andric 
2730b57cec5SDimitry Andric       SmallVector<ICToken, 16> OperandStack;
274cb14a3feSDimitry Andric       for (const ICToken &Op : PostfixStack) {
2750b57cec5SDimitry Andric         if (Op.first == IC_IMM || Op.first == IC_REGISTER) {
2760b57cec5SDimitry Andric           OperandStack.push_back(Op);
2770b57cec5SDimitry Andric         } else if (isUnaryOperator(Op.first)) {
2780b57cec5SDimitry Andric           assert (OperandStack.size() > 0 && "Too few operands.");
2790b57cec5SDimitry Andric           ICToken Operand = OperandStack.pop_back_val();
2800b57cec5SDimitry Andric           assert (Operand.first == IC_IMM &&
2810b57cec5SDimitry Andric                   "Unary operation with a register!");
2820b57cec5SDimitry Andric           switch (Op.first) {
2830b57cec5SDimitry Andric           default:
2840b57cec5SDimitry Andric             report_fatal_error("Unexpected operator!");
2850b57cec5SDimitry Andric             break;
2860b57cec5SDimitry Andric           case IC_NEG:
2870b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, -Operand.second));
2880b57cec5SDimitry Andric             break;
2890b57cec5SDimitry Andric           case IC_NOT:
2900b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, ~Operand.second));
2910b57cec5SDimitry Andric             break;
2920b57cec5SDimitry Andric           }
2930b57cec5SDimitry Andric         } else {
2940b57cec5SDimitry Andric           assert (OperandStack.size() > 1 && "Too few operands.");
2950b57cec5SDimitry Andric           int64_t Val;
2960b57cec5SDimitry Andric           ICToken Op2 = OperandStack.pop_back_val();
2970b57cec5SDimitry Andric           ICToken Op1 = OperandStack.pop_back_val();
2980b57cec5SDimitry Andric           switch (Op.first) {
2990b57cec5SDimitry Andric           default:
3000b57cec5SDimitry Andric             report_fatal_error("Unexpected operator!");
3010b57cec5SDimitry Andric             break;
3020b57cec5SDimitry Andric           case IC_PLUS:
3030b57cec5SDimitry Andric             Val = Op1.second + Op2.second;
3040b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
3050b57cec5SDimitry Andric             break;
3060b57cec5SDimitry Andric           case IC_MINUS:
3070b57cec5SDimitry Andric             Val = Op1.second - Op2.second;
3080b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
3090b57cec5SDimitry Andric             break;
3100b57cec5SDimitry Andric           case IC_MULTIPLY:
3110b57cec5SDimitry Andric             assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
3120b57cec5SDimitry Andric                     "Multiply operation with an immediate and a register!");
3130b57cec5SDimitry Andric             Val = Op1.second * Op2.second;
3140b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
3150b57cec5SDimitry Andric             break;
3160b57cec5SDimitry Andric           case IC_DIVIDE:
3170b57cec5SDimitry Andric             assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
3180b57cec5SDimitry Andric                     "Divide operation with an immediate and a register!");
3190b57cec5SDimitry Andric             assert (Op2.second != 0 && "Division by zero!");
3200b57cec5SDimitry Andric             Val = Op1.second / Op2.second;
3210b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
3220b57cec5SDimitry Andric             break;
3230b57cec5SDimitry Andric           case IC_MOD:
3240b57cec5SDimitry Andric             assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
3250b57cec5SDimitry Andric                     "Modulo operation with an immediate and a register!");
3260b57cec5SDimitry Andric             Val = Op1.second % Op2.second;
3270b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
3280b57cec5SDimitry Andric             break;
3290b57cec5SDimitry Andric           case IC_OR:
3300b57cec5SDimitry Andric             assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
3310b57cec5SDimitry Andric                     "Or operation with an immediate and a register!");
3320b57cec5SDimitry Andric             Val = Op1.second | Op2.second;
3330b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
3340b57cec5SDimitry Andric             break;
3350b57cec5SDimitry Andric           case IC_XOR:
3360b57cec5SDimitry Andric             assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
3370b57cec5SDimitry Andric               "Xor operation with an immediate and a register!");
3380b57cec5SDimitry Andric             Val = Op1.second ^ Op2.second;
3390b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
3400b57cec5SDimitry Andric             break;
3410b57cec5SDimitry Andric           case IC_AND:
3420b57cec5SDimitry Andric             assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
3430b57cec5SDimitry Andric                     "And operation with an immediate and a register!");
3440b57cec5SDimitry Andric             Val = Op1.second & Op2.second;
3450b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
3460b57cec5SDimitry Andric             break;
3470b57cec5SDimitry Andric           case IC_LSHIFT:
3480b57cec5SDimitry Andric             assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
3490b57cec5SDimitry Andric                     "Left shift operation with an immediate and a register!");
3500b57cec5SDimitry Andric             Val = Op1.second << Op2.second;
3510b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
3520b57cec5SDimitry Andric             break;
3530b57cec5SDimitry Andric           case IC_RSHIFT:
3540b57cec5SDimitry Andric             assert (Op1.first == IC_IMM && Op2.first == IC_IMM &&
3550b57cec5SDimitry Andric                     "Right shift operation with an immediate and a register!");
3560b57cec5SDimitry Andric             Val = Op1.second >> Op2.second;
3570b57cec5SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
3580b57cec5SDimitry Andric             break;
359e8d8bef9SDimitry Andric           case IC_EQ:
360e8d8bef9SDimitry Andric             assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
361e8d8bef9SDimitry Andric                    "Equals operation with an immediate and a register!");
362e8d8bef9SDimitry Andric             Val = (Op1.second == Op2.second) ? -1 : 0;
363e8d8bef9SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
364e8d8bef9SDimitry Andric             break;
365e8d8bef9SDimitry Andric           case IC_NE:
366e8d8bef9SDimitry Andric             assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
367e8d8bef9SDimitry Andric                    "Not-equals operation with an immediate and a register!");
368e8d8bef9SDimitry Andric             Val = (Op1.second != Op2.second) ? -1 : 0;
369e8d8bef9SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
370e8d8bef9SDimitry Andric             break;
371e8d8bef9SDimitry Andric           case IC_LT:
372e8d8bef9SDimitry Andric             assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
373e8d8bef9SDimitry Andric                    "Less-than operation with an immediate and a register!");
374e8d8bef9SDimitry Andric             Val = (Op1.second < Op2.second) ? -1 : 0;
375e8d8bef9SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
376e8d8bef9SDimitry Andric             break;
377e8d8bef9SDimitry Andric           case IC_LE:
378e8d8bef9SDimitry Andric             assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
379e8d8bef9SDimitry Andric                    "Less-than-or-equal operation with an immediate and a "
380e8d8bef9SDimitry Andric                    "register!");
381e8d8bef9SDimitry Andric             Val = (Op1.second <= Op2.second) ? -1 : 0;
382e8d8bef9SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
383e8d8bef9SDimitry Andric             break;
384e8d8bef9SDimitry Andric           case IC_GT:
385e8d8bef9SDimitry Andric             assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
386e8d8bef9SDimitry Andric                    "Greater-than operation with an immediate and a register!");
387e8d8bef9SDimitry Andric             Val = (Op1.second > Op2.second) ? -1 : 0;
388e8d8bef9SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
389e8d8bef9SDimitry Andric             break;
390e8d8bef9SDimitry Andric           case IC_GE:
391e8d8bef9SDimitry Andric             assert(Op1.first == IC_IMM && Op2.first == IC_IMM &&
392e8d8bef9SDimitry Andric                    "Greater-than-or-equal operation with an immediate and a "
393e8d8bef9SDimitry Andric                    "register!");
394e8d8bef9SDimitry Andric             Val = (Op1.second >= Op2.second) ? -1 : 0;
395e8d8bef9SDimitry Andric             OperandStack.push_back(std::make_pair(IC_IMM, Val));
396e8d8bef9SDimitry Andric             break;
3970b57cec5SDimitry Andric           }
3980b57cec5SDimitry Andric         }
3990b57cec5SDimitry Andric       }
4000b57cec5SDimitry Andric       assert (OperandStack.size() == 1 && "Expected a single result.");
4010b57cec5SDimitry Andric       return OperandStack.pop_back_val().second;
4020b57cec5SDimitry Andric     }
4030b57cec5SDimitry Andric   };
4040b57cec5SDimitry Andric 
4050b57cec5SDimitry Andric   enum IntelExprState {
4060b57cec5SDimitry Andric     IES_INIT,
4070b57cec5SDimitry Andric     IES_OR,
4080b57cec5SDimitry Andric     IES_XOR,
4090b57cec5SDimitry Andric     IES_AND,
410e8d8bef9SDimitry Andric     IES_EQ,
411e8d8bef9SDimitry Andric     IES_NE,
412e8d8bef9SDimitry Andric     IES_LT,
413e8d8bef9SDimitry Andric     IES_LE,
414e8d8bef9SDimitry Andric     IES_GT,
415e8d8bef9SDimitry Andric     IES_GE,
4160b57cec5SDimitry Andric     IES_LSHIFT,
4170b57cec5SDimitry Andric     IES_RSHIFT,
4180b57cec5SDimitry Andric     IES_PLUS,
4190b57cec5SDimitry Andric     IES_MINUS,
420480093f4SDimitry Andric     IES_OFFSET,
4215ffd83dbSDimitry Andric     IES_CAST,
4220b57cec5SDimitry Andric     IES_NOT,
4230b57cec5SDimitry Andric     IES_MULTIPLY,
4240b57cec5SDimitry Andric     IES_DIVIDE,
4250b57cec5SDimitry Andric     IES_MOD,
4260b57cec5SDimitry Andric     IES_LBRAC,
4270b57cec5SDimitry Andric     IES_RBRAC,
4280b57cec5SDimitry Andric     IES_LPAREN,
4290b57cec5SDimitry Andric     IES_RPAREN,
4300b57cec5SDimitry Andric     IES_REGISTER,
4310b57cec5SDimitry Andric     IES_INTEGER,
4320b57cec5SDimitry Andric     IES_ERROR
4330b57cec5SDimitry Andric   };
4340b57cec5SDimitry Andric 
4350b57cec5SDimitry Andric   class IntelExprStateMachine {
43681ad6265SDimitry Andric     IntelExprState State = IES_INIT, PrevState = IES_ERROR;
43781ad6265SDimitry Andric     unsigned BaseReg = 0, IndexReg = 0, TmpReg = 0, Scale = 0;
43881ad6265SDimitry Andric     int64_t Imm = 0;
43981ad6265SDimitry Andric     const MCExpr *Sym = nullptr;
4400b57cec5SDimitry Andric     StringRef SymName;
4410b57cec5SDimitry Andric     InfixCalculator IC;
4420b57cec5SDimitry Andric     InlineAsmIdentifierInfo Info;
44381ad6265SDimitry Andric     short BracCount = 0;
44481ad6265SDimitry Andric     bool MemExpr = false;
44506c3fb27SDimitry Andric     bool BracketUsed = false;
44681ad6265SDimitry Andric     bool OffsetOperator = false;
44781ad6265SDimitry Andric     bool AttachToOperandIdx = false;
44881ad6265SDimitry Andric     bool IsPIC = false;
449480093f4SDimitry Andric     SMLoc OffsetOperatorLoc;
450e8d8bef9SDimitry Andric     AsmTypeInfo CurType;
451480093f4SDimitry Andric 
setSymRef(const MCExpr * Val,StringRef ID,StringRef & ErrMsg)452480093f4SDimitry Andric     bool setSymRef(const MCExpr *Val, StringRef ID, StringRef &ErrMsg) {
453480093f4SDimitry Andric       if (Sym) {
454480093f4SDimitry Andric         ErrMsg = "cannot use more than one symbol in memory operand";
455480093f4SDimitry Andric         return true;
456480093f4SDimitry Andric       }
457480093f4SDimitry Andric       Sym = Val;
458480093f4SDimitry Andric       SymName = ID;
459480093f4SDimitry Andric       return false;
460480093f4SDimitry Andric     }
4610b57cec5SDimitry Andric 
4620b57cec5SDimitry Andric   public:
46381ad6265SDimitry Andric     IntelExprStateMachine() = default;
4640b57cec5SDimitry Andric 
addImm(int64_t imm)4650b57cec5SDimitry Andric     void addImm(int64_t imm) { Imm += imm; }
getBracCount() const466e8d8bef9SDimitry Andric     short getBracCount() const { return BracCount; }
isMemExpr() const467e8d8bef9SDimitry Andric     bool isMemExpr() const { return MemExpr; }
isBracketUsed() const46806c3fb27SDimitry Andric     bool isBracketUsed() const { return BracketUsed; }
isOffsetOperator() const469e8d8bef9SDimitry Andric     bool isOffsetOperator() const { return OffsetOperator; }
getOffsetLoc() const470e8d8bef9SDimitry Andric     SMLoc getOffsetLoc() const { return OffsetOperatorLoc; }
getBaseReg() const471e8d8bef9SDimitry Andric     unsigned getBaseReg() const { return BaseReg; }
getIndexReg() const472e8d8bef9SDimitry Andric     unsigned getIndexReg() const { return IndexReg; }
getScale() const473e8d8bef9SDimitry Andric     unsigned getScale() const { return Scale; }
getSym() const474e8d8bef9SDimitry Andric     const MCExpr *getSym() const { return Sym; }
getSymName() const475e8d8bef9SDimitry Andric     StringRef getSymName() const { return SymName; }
getType() const476e8d8bef9SDimitry Andric     StringRef getType() const { return CurType.Name; }
getSize() const477e8d8bef9SDimitry Andric     unsigned getSize() const { return CurType.Size; }
getElementSize() const478e8d8bef9SDimitry Andric     unsigned getElementSize() const { return CurType.ElementSize; }
getLength() const479e8d8bef9SDimitry Andric     unsigned getLength() const { return CurType.Length; }
getImm()4800b57cec5SDimitry Andric     int64_t getImm() { return Imm + IC.execute(); }
isValidEndState() const481e8d8bef9SDimitry Andric     bool isValidEndState() const {
4820fca6ea1SDimitry Andric       return State == IES_RBRAC || State == IES_RPAREN ||
4830fca6ea1SDimitry Andric              State == IES_INTEGER || State == IES_REGISTER ||
4840fca6ea1SDimitry Andric              State == IES_OFFSET;
4850b57cec5SDimitry Andric     }
48681ad6265SDimitry Andric 
48781ad6265SDimitry Andric     // Is the intel expression appended after an operand index.
48881ad6265SDimitry Andric     // [OperandIdx][Intel Expression]
48981ad6265SDimitry Andric     // This is neccessary for checking if it is an independent
49081ad6265SDimitry Andric     // intel expression at back end when parse inline asm.
setAppendAfterOperand()49181ad6265SDimitry Andric     void setAppendAfterOperand() { AttachToOperandIdx = true; }
49281ad6265SDimitry Andric 
isPIC() const49381ad6265SDimitry Andric     bool isPIC() const { return IsPIC; }
setPIC()49481ad6265SDimitry Andric     void setPIC() { IsPIC = true; }
49581ad6265SDimitry Andric 
hadError() const496e8d8bef9SDimitry Andric     bool hadError() const { return State == IES_ERROR; }
getIdentifierInfo() const497e8d8bef9SDimitry Andric     const InlineAsmIdentifierInfo &getIdentifierInfo() const { return Info; }
4980b57cec5SDimitry Andric 
regsUseUpError(StringRef & ErrMsg)49981ad6265SDimitry Andric     bool regsUseUpError(StringRef &ErrMsg) {
50081ad6265SDimitry Andric       // This case mostly happen in inline asm, e.g. Arr[BaseReg + IndexReg]
50181ad6265SDimitry Andric       // can not intruduce additional register in inline asm in PIC model.
50281ad6265SDimitry Andric       if (IsPIC && AttachToOperandIdx)
50381ad6265SDimitry Andric         ErrMsg = "Don't use 2 or more regs for mem offset in PIC model!";
50481ad6265SDimitry Andric       else
50581ad6265SDimitry Andric         ErrMsg = "BaseReg/IndexReg already set!";
50681ad6265SDimitry Andric       return true;
50781ad6265SDimitry Andric     }
50881ad6265SDimitry Andric 
onOr()5090b57cec5SDimitry Andric     void onOr() {
5100b57cec5SDimitry Andric       IntelExprState CurrState = State;
5110b57cec5SDimitry Andric       switch (State) {
5120b57cec5SDimitry Andric       default:
5130b57cec5SDimitry Andric         State = IES_ERROR;
5140b57cec5SDimitry Andric         break;
5150b57cec5SDimitry Andric       case IES_INTEGER:
5160b57cec5SDimitry Andric       case IES_RPAREN:
5170b57cec5SDimitry Andric       case IES_REGISTER:
5180b57cec5SDimitry Andric         State = IES_OR;
5190b57cec5SDimitry Andric         IC.pushOperator(IC_OR);
5200b57cec5SDimitry Andric         break;
5210b57cec5SDimitry Andric       }
5220b57cec5SDimitry Andric       PrevState = CurrState;
5230b57cec5SDimitry Andric     }
onXor()5240b57cec5SDimitry Andric     void onXor() {
5250b57cec5SDimitry Andric       IntelExprState CurrState = State;
5260b57cec5SDimitry Andric       switch (State) {
5270b57cec5SDimitry Andric       default:
5280b57cec5SDimitry Andric         State = IES_ERROR;
5290b57cec5SDimitry Andric         break;
5300b57cec5SDimitry Andric       case IES_INTEGER:
5310b57cec5SDimitry Andric       case IES_RPAREN:
5320b57cec5SDimitry Andric       case IES_REGISTER:
5330b57cec5SDimitry Andric         State = IES_XOR;
5340b57cec5SDimitry Andric         IC.pushOperator(IC_XOR);
5350b57cec5SDimitry Andric         break;
5360b57cec5SDimitry Andric       }
5370b57cec5SDimitry Andric       PrevState = CurrState;
5380b57cec5SDimitry Andric     }
onAnd()5390b57cec5SDimitry Andric     void onAnd() {
5400b57cec5SDimitry Andric       IntelExprState CurrState = State;
5410b57cec5SDimitry Andric       switch (State) {
5420b57cec5SDimitry Andric       default:
5430b57cec5SDimitry Andric         State = IES_ERROR;
5440b57cec5SDimitry Andric         break;
5450b57cec5SDimitry Andric       case IES_INTEGER:
5460b57cec5SDimitry Andric       case IES_RPAREN:
5470b57cec5SDimitry Andric       case IES_REGISTER:
5480b57cec5SDimitry Andric         State = IES_AND;
5490b57cec5SDimitry Andric         IC.pushOperator(IC_AND);
5500b57cec5SDimitry Andric         break;
5510b57cec5SDimitry Andric       }
5520b57cec5SDimitry Andric       PrevState = CurrState;
5530b57cec5SDimitry Andric     }
onEq()554e8d8bef9SDimitry Andric     void onEq() {
555e8d8bef9SDimitry Andric       IntelExprState CurrState = State;
556e8d8bef9SDimitry Andric       switch (State) {
557e8d8bef9SDimitry Andric       default:
558e8d8bef9SDimitry Andric         State = IES_ERROR;
559e8d8bef9SDimitry Andric         break;
560e8d8bef9SDimitry Andric       case IES_INTEGER:
561e8d8bef9SDimitry Andric       case IES_RPAREN:
562e8d8bef9SDimitry Andric       case IES_REGISTER:
563e8d8bef9SDimitry Andric         State = IES_EQ;
564e8d8bef9SDimitry Andric         IC.pushOperator(IC_EQ);
565e8d8bef9SDimitry Andric         break;
566e8d8bef9SDimitry Andric       }
567e8d8bef9SDimitry Andric       PrevState = CurrState;
568e8d8bef9SDimitry Andric     }
onNE()569e8d8bef9SDimitry Andric     void onNE() {
570e8d8bef9SDimitry Andric       IntelExprState CurrState = State;
571e8d8bef9SDimitry Andric       switch (State) {
572e8d8bef9SDimitry Andric       default:
573e8d8bef9SDimitry Andric         State = IES_ERROR;
574e8d8bef9SDimitry Andric         break;
575e8d8bef9SDimitry Andric       case IES_INTEGER:
576e8d8bef9SDimitry Andric       case IES_RPAREN:
577e8d8bef9SDimitry Andric       case IES_REGISTER:
578e8d8bef9SDimitry Andric         State = IES_NE;
579e8d8bef9SDimitry Andric         IC.pushOperator(IC_NE);
580e8d8bef9SDimitry Andric         break;
581e8d8bef9SDimitry Andric       }
582e8d8bef9SDimitry Andric       PrevState = CurrState;
583e8d8bef9SDimitry Andric     }
onLT()584e8d8bef9SDimitry Andric     void onLT() {
585e8d8bef9SDimitry Andric       IntelExprState CurrState = State;
586e8d8bef9SDimitry Andric       switch (State) {
587e8d8bef9SDimitry Andric       default:
588e8d8bef9SDimitry Andric         State = IES_ERROR;
589e8d8bef9SDimitry Andric         break;
590e8d8bef9SDimitry Andric       case IES_INTEGER:
591e8d8bef9SDimitry Andric       case IES_RPAREN:
592e8d8bef9SDimitry Andric       case IES_REGISTER:
593e8d8bef9SDimitry Andric         State = IES_LT;
594e8d8bef9SDimitry Andric         IC.pushOperator(IC_LT);
595e8d8bef9SDimitry Andric         break;
596e8d8bef9SDimitry Andric       }
597e8d8bef9SDimitry Andric       PrevState = CurrState;
598e8d8bef9SDimitry Andric     }
onLE()599e8d8bef9SDimitry Andric     void onLE() {
600e8d8bef9SDimitry Andric       IntelExprState CurrState = State;
601e8d8bef9SDimitry Andric       switch (State) {
602e8d8bef9SDimitry Andric       default:
603e8d8bef9SDimitry Andric         State = IES_ERROR;
604e8d8bef9SDimitry Andric         break;
605e8d8bef9SDimitry Andric       case IES_INTEGER:
606e8d8bef9SDimitry Andric       case IES_RPAREN:
607e8d8bef9SDimitry Andric       case IES_REGISTER:
608e8d8bef9SDimitry Andric         State = IES_LE;
609e8d8bef9SDimitry Andric         IC.pushOperator(IC_LE);
610e8d8bef9SDimitry Andric         break;
611e8d8bef9SDimitry Andric       }
612e8d8bef9SDimitry Andric       PrevState = CurrState;
613e8d8bef9SDimitry Andric     }
onGT()614e8d8bef9SDimitry Andric     void onGT() {
615e8d8bef9SDimitry Andric       IntelExprState CurrState = State;
616e8d8bef9SDimitry Andric       switch (State) {
617e8d8bef9SDimitry Andric       default:
618e8d8bef9SDimitry Andric         State = IES_ERROR;
619e8d8bef9SDimitry Andric         break;
620e8d8bef9SDimitry Andric       case IES_INTEGER:
621e8d8bef9SDimitry Andric       case IES_RPAREN:
622e8d8bef9SDimitry Andric       case IES_REGISTER:
623e8d8bef9SDimitry Andric         State = IES_GT;
624e8d8bef9SDimitry Andric         IC.pushOperator(IC_GT);
625e8d8bef9SDimitry Andric         break;
626e8d8bef9SDimitry Andric       }
627e8d8bef9SDimitry Andric       PrevState = CurrState;
628e8d8bef9SDimitry Andric     }
onGE()629e8d8bef9SDimitry Andric     void onGE() {
630e8d8bef9SDimitry Andric       IntelExprState CurrState = State;
631e8d8bef9SDimitry Andric       switch (State) {
632e8d8bef9SDimitry Andric       default:
633e8d8bef9SDimitry Andric         State = IES_ERROR;
634e8d8bef9SDimitry Andric         break;
635e8d8bef9SDimitry Andric       case IES_INTEGER:
636e8d8bef9SDimitry Andric       case IES_RPAREN:
637e8d8bef9SDimitry Andric       case IES_REGISTER:
638e8d8bef9SDimitry Andric         State = IES_GE;
639e8d8bef9SDimitry Andric         IC.pushOperator(IC_GE);
640e8d8bef9SDimitry Andric         break;
641e8d8bef9SDimitry Andric       }
642e8d8bef9SDimitry Andric       PrevState = CurrState;
643e8d8bef9SDimitry Andric     }
onLShift()6440b57cec5SDimitry Andric     void onLShift() {
6450b57cec5SDimitry Andric       IntelExprState CurrState = State;
6460b57cec5SDimitry Andric       switch (State) {
6470b57cec5SDimitry Andric       default:
6480b57cec5SDimitry Andric         State = IES_ERROR;
6490b57cec5SDimitry Andric         break;
6500b57cec5SDimitry Andric       case IES_INTEGER:
6510b57cec5SDimitry Andric       case IES_RPAREN:
6520b57cec5SDimitry Andric       case IES_REGISTER:
6530b57cec5SDimitry Andric         State = IES_LSHIFT;
6540b57cec5SDimitry Andric         IC.pushOperator(IC_LSHIFT);
6550b57cec5SDimitry Andric         break;
6560b57cec5SDimitry Andric       }
6570b57cec5SDimitry Andric       PrevState = CurrState;
6580b57cec5SDimitry Andric     }
onRShift()6590b57cec5SDimitry Andric     void onRShift() {
6600b57cec5SDimitry Andric       IntelExprState CurrState = State;
6610b57cec5SDimitry Andric       switch (State) {
6620b57cec5SDimitry Andric       default:
6630b57cec5SDimitry Andric         State = IES_ERROR;
6640b57cec5SDimitry Andric         break;
6650b57cec5SDimitry Andric       case IES_INTEGER:
6660b57cec5SDimitry Andric       case IES_RPAREN:
6670b57cec5SDimitry Andric       case IES_REGISTER:
6680b57cec5SDimitry Andric         State = IES_RSHIFT;
6690b57cec5SDimitry Andric         IC.pushOperator(IC_RSHIFT);
6700b57cec5SDimitry Andric         break;
6710b57cec5SDimitry Andric       }
6720b57cec5SDimitry Andric       PrevState = CurrState;
6730b57cec5SDimitry Andric     }
onPlus(StringRef & ErrMsg)6740b57cec5SDimitry Andric     bool onPlus(StringRef &ErrMsg) {
6750b57cec5SDimitry Andric       IntelExprState CurrState = State;
6760b57cec5SDimitry Andric       switch (State) {
6770b57cec5SDimitry Andric       default:
6780b57cec5SDimitry Andric         State = IES_ERROR;
6790b57cec5SDimitry Andric         break;
6800b57cec5SDimitry Andric       case IES_INTEGER:
6810b57cec5SDimitry Andric       case IES_RPAREN:
6820b57cec5SDimitry Andric       case IES_REGISTER:
683480093f4SDimitry Andric       case IES_OFFSET:
6840b57cec5SDimitry Andric         State = IES_PLUS;
6850b57cec5SDimitry Andric         IC.pushOperator(IC_PLUS);
6860b57cec5SDimitry Andric         if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
6870b57cec5SDimitry Andric           // If we already have a BaseReg, then assume this is the IndexReg with
6880b57cec5SDimitry Andric           // no explicit scale.
6890b57cec5SDimitry Andric           if (!BaseReg) {
6900b57cec5SDimitry Andric             BaseReg = TmpReg;
6910b57cec5SDimitry Andric           } else {
69281ad6265SDimitry Andric             if (IndexReg)
69381ad6265SDimitry Andric               return regsUseUpError(ErrMsg);
6940b57cec5SDimitry Andric             IndexReg = TmpReg;
6950b57cec5SDimitry Andric             Scale = 0;
6960b57cec5SDimitry Andric           }
6970b57cec5SDimitry Andric         }
6980b57cec5SDimitry Andric         break;
6990b57cec5SDimitry Andric       }
7000b57cec5SDimitry Andric       PrevState = CurrState;
7010b57cec5SDimitry Andric       return false;
7020b57cec5SDimitry Andric     }
onMinus(StringRef & ErrMsg)7030b57cec5SDimitry Andric     bool onMinus(StringRef &ErrMsg) {
7040b57cec5SDimitry Andric       IntelExprState CurrState = State;
7050b57cec5SDimitry Andric       switch (State) {
7060b57cec5SDimitry Andric       default:
7070b57cec5SDimitry Andric         State = IES_ERROR;
7080b57cec5SDimitry Andric         break;
7090b57cec5SDimitry Andric       case IES_OR:
7100b57cec5SDimitry Andric       case IES_XOR:
7110b57cec5SDimitry Andric       case IES_AND:
712e8d8bef9SDimitry Andric       case IES_EQ:
713e8d8bef9SDimitry Andric       case IES_NE:
714e8d8bef9SDimitry Andric       case IES_LT:
715e8d8bef9SDimitry Andric       case IES_LE:
716e8d8bef9SDimitry Andric       case IES_GT:
717e8d8bef9SDimitry Andric       case IES_GE:
7180b57cec5SDimitry Andric       case IES_LSHIFT:
7190b57cec5SDimitry Andric       case IES_RSHIFT:
7200b57cec5SDimitry Andric       case IES_PLUS:
7210b57cec5SDimitry Andric       case IES_NOT:
7220b57cec5SDimitry Andric       case IES_MULTIPLY:
7230b57cec5SDimitry Andric       case IES_DIVIDE:
7240b57cec5SDimitry Andric       case IES_MOD:
7250b57cec5SDimitry Andric       case IES_LPAREN:
7260b57cec5SDimitry Andric       case IES_RPAREN:
7270b57cec5SDimitry Andric       case IES_LBRAC:
7280b57cec5SDimitry Andric       case IES_RBRAC:
7290b57cec5SDimitry Andric       case IES_INTEGER:
7300b57cec5SDimitry Andric       case IES_REGISTER:
7310b57cec5SDimitry Andric       case IES_INIT:
732480093f4SDimitry Andric       case IES_OFFSET:
7330b57cec5SDimitry Andric         State = IES_MINUS;
7340b57cec5SDimitry Andric         // push minus operator if it is not a negate operator
7350b57cec5SDimitry Andric         if (CurrState == IES_REGISTER || CurrState == IES_RPAREN ||
736480093f4SDimitry Andric             CurrState == IES_INTEGER  || CurrState == IES_RBRAC  ||
737480093f4SDimitry Andric             CurrState == IES_OFFSET)
7380b57cec5SDimitry Andric           IC.pushOperator(IC_MINUS);
7390b57cec5SDimitry Andric         else if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
7400b57cec5SDimitry Andric           // We have negate operator for Scale: it's illegal
7410b57cec5SDimitry Andric           ErrMsg = "Scale can't be negative";
7420b57cec5SDimitry Andric           return true;
7430b57cec5SDimitry Andric         } else
7440b57cec5SDimitry Andric           IC.pushOperator(IC_NEG);
7450b57cec5SDimitry Andric         if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
7460b57cec5SDimitry Andric           // If we already have a BaseReg, then assume this is the IndexReg with
7470b57cec5SDimitry Andric           // no explicit scale.
7480b57cec5SDimitry Andric           if (!BaseReg) {
7490b57cec5SDimitry Andric             BaseReg = TmpReg;
7500b57cec5SDimitry Andric           } else {
75181ad6265SDimitry Andric             if (IndexReg)
75281ad6265SDimitry Andric               return regsUseUpError(ErrMsg);
7530b57cec5SDimitry Andric             IndexReg = TmpReg;
7540b57cec5SDimitry Andric             Scale = 0;
7550b57cec5SDimitry Andric           }
7560b57cec5SDimitry Andric         }
7570b57cec5SDimitry Andric         break;
7580b57cec5SDimitry Andric       }
7590b57cec5SDimitry Andric       PrevState = CurrState;
7600b57cec5SDimitry Andric       return false;
7610b57cec5SDimitry Andric     }
onNot()7620b57cec5SDimitry Andric     void onNot() {
7630b57cec5SDimitry Andric       IntelExprState CurrState = State;
7640b57cec5SDimitry Andric       switch (State) {
7650b57cec5SDimitry Andric       default:
7660b57cec5SDimitry Andric         State = IES_ERROR;
7670b57cec5SDimitry Andric         break;
7680b57cec5SDimitry Andric       case IES_OR:
7690b57cec5SDimitry Andric       case IES_XOR:
7700b57cec5SDimitry Andric       case IES_AND:
771e8d8bef9SDimitry Andric       case IES_EQ:
772e8d8bef9SDimitry Andric       case IES_NE:
773e8d8bef9SDimitry Andric       case IES_LT:
774e8d8bef9SDimitry Andric       case IES_LE:
775e8d8bef9SDimitry Andric       case IES_GT:
776e8d8bef9SDimitry Andric       case IES_GE:
7770b57cec5SDimitry Andric       case IES_LSHIFT:
7780b57cec5SDimitry Andric       case IES_RSHIFT:
7790b57cec5SDimitry Andric       case IES_PLUS:
7800b57cec5SDimitry Andric       case IES_MINUS:
7810b57cec5SDimitry Andric       case IES_NOT:
7820b57cec5SDimitry Andric       case IES_MULTIPLY:
7830b57cec5SDimitry Andric       case IES_DIVIDE:
7840b57cec5SDimitry Andric       case IES_MOD:
7850b57cec5SDimitry Andric       case IES_LPAREN:
7860b57cec5SDimitry Andric       case IES_LBRAC:
7870b57cec5SDimitry Andric       case IES_INIT:
7880b57cec5SDimitry Andric         State = IES_NOT;
7890b57cec5SDimitry Andric         IC.pushOperator(IC_NOT);
7900b57cec5SDimitry Andric         break;
7910b57cec5SDimitry Andric       }
7920b57cec5SDimitry Andric       PrevState = CurrState;
7930b57cec5SDimitry Andric     }
onRegister(unsigned Reg,StringRef & ErrMsg)7940b57cec5SDimitry Andric     bool onRegister(unsigned Reg, StringRef &ErrMsg) {
7950b57cec5SDimitry Andric       IntelExprState CurrState = State;
7960b57cec5SDimitry Andric       switch (State) {
7970b57cec5SDimitry Andric       default:
7980b57cec5SDimitry Andric         State = IES_ERROR;
7990b57cec5SDimitry Andric         break;
8000b57cec5SDimitry Andric       case IES_PLUS:
8010b57cec5SDimitry Andric       case IES_LPAREN:
8020b57cec5SDimitry Andric       case IES_LBRAC:
8030b57cec5SDimitry Andric         State = IES_REGISTER;
8040b57cec5SDimitry Andric         TmpReg = Reg;
8050b57cec5SDimitry Andric         IC.pushOperand(IC_REGISTER);
8060b57cec5SDimitry Andric         break;
8070b57cec5SDimitry Andric       case IES_MULTIPLY:
8080b57cec5SDimitry Andric         // Index Register - Scale * Register
8090b57cec5SDimitry Andric         if (PrevState == IES_INTEGER) {
81081ad6265SDimitry Andric           if (IndexReg)
81181ad6265SDimitry Andric             return regsUseUpError(ErrMsg);
8120b57cec5SDimitry Andric           State = IES_REGISTER;
8130b57cec5SDimitry Andric           IndexReg = Reg;
8140b57cec5SDimitry Andric           // Get the scale and replace the 'Scale * Register' with '0'.
8150b57cec5SDimitry Andric           Scale = IC.popOperand();
8160b57cec5SDimitry Andric           if (checkScale(Scale, ErrMsg))
8170b57cec5SDimitry Andric             return true;
8180b57cec5SDimitry Andric           IC.pushOperand(IC_IMM);
8190b57cec5SDimitry Andric           IC.popOperator();
8200b57cec5SDimitry Andric         } else {
8210b57cec5SDimitry Andric           State = IES_ERROR;
8220b57cec5SDimitry Andric         }
8230b57cec5SDimitry Andric         break;
8240b57cec5SDimitry Andric       }
8250b57cec5SDimitry Andric       PrevState = CurrState;
8260b57cec5SDimitry Andric       return false;
8270b57cec5SDimitry Andric     }
onIdentifierExpr(const MCExpr * SymRef,StringRef SymRefName,const InlineAsmIdentifierInfo & IDInfo,const AsmTypeInfo & Type,bool ParsingMSInlineAsm,StringRef & ErrMsg)8280b57cec5SDimitry Andric     bool onIdentifierExpr(const MCExpr *SymRef, StringRef SymRefName,
8290b57cec5SDimitry Andric                           const InlineAsmIdentifierInfo &IDInfo,
830e8d8bef9SDimitry Andric                           const AsmTypeInfo &Type, bool ParsingMSInlineAsm,
831e8d8bef9SDimitry Andric                           StringRef &ErrMsg) {
8320b57cec5SDimitry Andric       // InlineAsm: Treat an enum value as an integer
8335ffd83dbSDimitry Andric       if (ParsingMSInlineAsm)
8340b57cec5SDimitry Andric         if (IDInfo.isKind(InlineAsmIdentifierInfo::IK_EnumVal))
8350b57cec5SDimitry Andric           return onInteger(IDInfo.Enum.EnumVal, ErrMsg);
8360b57cec5SDimitry Andric       // Treat a symbolic constant like an integer
8370b57cec5SDimitry Andric       if (auto *CE = dyn_cast<MCConstantExpr>(SymRef))
8380b57cec5SDimitry Andric         return onInteger(CE->getValue(), ErrMsg);
8390b57cec5SDimitry Andric       PrevState = State;
8400b57cec5SDimitry Andric       switch (State) {
8410b57cec5SDimitry Andric       default:
8420b57cec5SDimitry Andric         State = IES_ERROR;
8430b57cec5SDimitry Andric         break;
8445ffd83dbSDimitry Andric       case IES_CAST:
8450b57cec5SDimitry Andric       case IES_PLUS:
8460b57cec5SDimitry Andric       case IES_MINUS:
8470b57cec5SDimitry Andric       case IES_NOT:
8480b57cec5SDimitry Andric       case IES_INIT:
8490b57cec5SDimitry Andric       case IES_LBRAC:
850e8d8bef9SDimitry Andric       case IES_LPAREN:
851480093f4SDimitry Andric         if (setSymRef(SymRef, SymRefName, ErrMsg))
852480093f4SDimitry Andric           return true;
8530b57cec5SDimitry Andric         MemExpr = true;
8540b57cec5SDimitry Andric         State = IES_INTEGER;
8550b57cec5SDimitry Andric         IC.pushOperand(IC_IMM);
8565ffd83dbSDimitry Andric         if (ParsingMSInlineAsm)
8570b57cec5SDimitry Andric           Info = IDInfo;
858e8d8bef9SDimitry Andric         setTypeInfo(Type);
8590b57cec5SDimitry Andric         break;
8600b57cec5SDimitry Andric       }
861480093f4SDimitry Andric       return false;
8620b57cec5SDimitry Andric     }
onInteger(int64_t TmpInt,StringRef & ErrMsg)8630b57cec5SDimitry Andric     bool onInteger(int64_t TmpInt, StringRef &ErrMsg) {
8640b57cec5SDimitry Andric       IntelExprState CurrState = State;
8650b57cec5SDimitry Andric       switch (State) {
8660b57cec5SDimitry Andric       default:
8670b57cec5SDimitry Andric         State = IES_ERROR;
8680b57cec5SDimitry Andric         break;
8690b57cec5SDimitry Andric       case IES_PLUS:
8700b57cec5SDimitry Andric       case IES_MINUS:
8710b57cec5SDimitry Andric       case IES_NOT:
8720b57cec5SDimitry Andric       case IES_OR:
8730b57cec5SDimitry Andric       case IES_XOR:
8740b57cec5SDimitry Andric       case IES_AND:
875e8d8bef9SDimitry Andric       case IES_EQ:
876e8d8bef9SDimitry Andric       case IES_NE:
877e8d8bef9SDimitry Andric       case IES_LT:
878e8d8bef9SDimitry Andric       case IES_LE:
879e8d8bef9SDimitry Andric       case IES_GT:
880e8d8bef9SDimitry Andric       case IES_GE:
8810b57cec5SDimitry Andric       case IES_LSHIFT:
8820b57cec5SDimitry Andric       case IES_RSHIFT:
8830b57cec5SDimitry Andric       case IES_DIVIDE:
8840b57cec5SDimitry Andric       case IES_MOD:
8850b57cec5SDimitry Andric       case IES_MULTIPLY:
8860b57cec5SDimitry Andric       case IES_LPAREN:
8870b57cec5SDimitry Andric       case IES_INIT:
8880b57cec5SDimitry Andric       case IES_LBRAC:
8890b57cec5SDimitry Andric         State = IES_INTEGER;
8900b57cec5SDimitry Andric         if (PrevState == IES_REGISTER && CurrState == IES_MULTIPLY) {
8910b57cec5SDimitry Andric           // Index Register - Register * Scale
89281ad6265SDimitry Andric           if (IndexReg)
89381ad6265SDimitry Andric             return regsUseUpError(ErrMsg);
8940b57cec5SDimitry Andric           IndexReg = TmpReg;
8950b57cec5SDimitry Andric           Scale = TmpInt;
8960b57cec5SDimitry Andric           if (checkScale(Scale, ErrMsg))
8970b57cec5SDimitry Andric             return true;
8980b57cec5SDimitry Andric           // Get the scale and replace the 'Register * Scale' with '0'.
8990b57cec5SDimitry Andric           IC.popOperator();
9000b57cec5SDimitry Andric         } else {
9010b57cec5SDimitry Andric           IC.pushOperand(IC_IMM, TmpInt);
9020b57cec5SDimitry Andric         }
9030b57cec5SDimitry Andric         break;
9040b57cec5SDimitry Andric       }
9050b57cec5SDimitry Andric       PrevState = CurrState;
9060b57cec5SDimitry Andric       return false;
9070b57cec5SDimitry Andric     }
onStar()9080b57cec5SDimitry Andric     void onStar() {
9090b57cec5SDimitry Andric       PrevState = State;
9100b57cec5SDimitry Andric       switch (State) {
9110b57cec5SDimitry Andric       default:
9120b57cec5SDimitry Andric         State = IES_ERROR;
9130b57cec5SDimitry Andric         break;
9140b57cec5SDimitry Andric       case IES_INTEGER:
9150b57cec5SDimitry Andric       case IES_REGISTER:
9160b57cec5SDimitry Andric       case IES_RPAREN:
9170b57cec5SDimitry Andric         State = IES_MULTIPLY;
9180b57cec5SDimitry Andric         IC.pushOperator(IC_MULTIPLY);
9190b57cec5SDimitry Andric         break;
9200b57cec5SDimitry Andric       }
9210b57cec5SDimitry Andric     }
onDivide()9220b57cec5SDimitry Andric     void onDivide() {
9230b57cec5SDimitry Andric       PrevState = State;
9240b57cec5SDimitry Andric       switch (State) {
9250b57cec5SDimitry Andric       default:
9260b57cec5SDimitry Andric         State = IES_ERROR;
9270b57cec5SDimitry Andric         break;
9280b57cec5SDimitry Andric       case IES_INTEGER:
9290b57cec5SDimitry Andric       case IES_RPAREN:
9300b57cec5SDimitry Andric         State = IES_DIVIDE;
9310b57cec5SDimitry Andric         IC.pushOperator(IC_DIVIDE);
9320b57cec5SDimitry Andric         break;
9330b57cec5SDimitry Andric       }
9340b57cec5SDimitry Andric     }
onMod()9350b57cec5SDimitry Andric     void onMod() {
9360b57cec5SDimitry Andric       PrevState = State;
9370b57cec5SDimitry Andric       switch (State) {
9380b57cec5SDimitry Andric       default:
9390b57cec5SDimitry Andric         State = IES_ERROR;
9400b57cec5SDimitry Andric         break;
9410b57cec5SDimitry Andric       case IES_INTEGER:
9420b57cec5SDimitry Andric       case IES_RPAREN:
9430b57cec5SDimitry Andric         State = IES_MOD;
9440b57cec5SDimitry Andric         IC.pushOperator(IC_MOD);
9450b57cec5SDimitry Andric         break;
9460b57cec5SDimitry Andric       }
9470b57cec5SDimitry Andric     }
onLBrac()9480b57cec5SDimitry Andric     bool onLBrac() {
9490b57cec5SDimitry Andric       if (BracCount)
9500b57cec5SDimitry Andric         return true;
9510b57cec5SDimitry Andric       PrevState = State;
9520b57cec5SDimitry Andric       switch (State) {
9530b57cec5SDimitry Andric       default:
9540b57cec5SDimitry Andric         State = IES_ERROR;
9550b57cec5SDimitry Andric         break;
9560b57cec5SDimitry Andric       case IES_RBRAC:
9570b57cec5SDimitry Andric       case IES_INTEGER:
9580b57cec5SDimitry Andric       case IES_RPAREN:
9590b57cec5SDimitry Andric         State = IES_PLUS;
9600b57cec5SDimitry Andric         IC.pushOperator(IC_PLUS);
961e8d8bef9SDimitry Andric         CurType.Length = 1;
962e8d8bef9SDimitry Andric         CurType.Size = CurType.ElementSize;
9630b57cec5SDimitry Andric         break;
9640b57cec5SDimitry Andric       case IES_INIT:
9655ffd83dbSDimitry Andric       case IES_CAST:
9660b57cec5SDimitry Andric         assert(!BracCount && "BracCount should be zero on parsing's start");
9670b57cec5SDimitry Andric         State = IES_LBRAC;
9680b57cec5SDimitry Andric         break;
9690b57cec5SDimitry Andric       }
9700b57cec5SDimitry Andric       MemExpr = true;
97106c3fb27SDimitry Andric       BracketUsed = true;
9720b57cec5SDimitry Andric       BracCount++;
9730b57cec5SDimitry Andric       return false;
9740b57cec5SDimitry Andric     }
onRBrac(StringRef & ErrMsg)97581ad6265SDimitry Andric     bool onRBrac(StringRef &ErrMsg) {
9760b57cec5SDimitry Andric       IntelExprState CurrState = State;
9770b57cec5SDimitry Andric       switch (State) {
9780b57cec5SDimitry Andric       default:
9790b57cec5SDimitry Andric         State = IES_ERROR;
9800b57cec5SDimitry Andric         break;
9810b57cec5SDimitry Andric       case IES_INTEGER:
982480093f4SDimitry Andric       case IES_OFFSET:
9830b57cec5SDimitry Andric       case IES_REGISTER:
9840b57cec5SDimitry Andric       case IES_RPAREN:
98581ad6265SDimitry Andric         if (BracCount-- != 1) {
98681ad6265SDimitry Andric           ErrMsg = "unexpected bracket encountered";
9870b57cec5SDimitry Andric           return true;
98881ad6265SDimitry Andric         }
9890b57cec5SDimitry Andric         State = IES_RBRAC;
9900b57cec5SDimitry Andric         if (CurrState == IES_REGISTER && PrevState != IES_MULTIPLY) {
9910b57cec5SDimitry Andric           // If we already have a BaseReg, then assume this is the IndexReg with
9920b57cec5SDimitry Andric           // no explicit scale.
9930b57cec5SDimitry Andric           if (!BaseReg) {
9940b57cec5SDimitry Andric             BaseReg = TmpReg;
9950b57cec5SDimitry Andric           } else {
99681ad6265SDimitry Andric             if (IndexReg)
99781ad6265SDimitry Andric               return regsUseUpError(ErrMsg);
9980b57cec5SDimitry Andric             IndexReg = TmpReg;
9990b57cec5SDimitry Andric             Scale = 0;
10000b57cec5SDimitry Andric           }
10010b57cec5SDimitry Andric         }
10020b57cec5SDimitry Andric         break;
10030b57cec5SDimitry Andric       }
10040b57cec5SDimitry Andric       PrevState = CurrState;
10050b57cec5SDimitry Andric       return false;
10060b57cec5SDimitry Andric     }
onLParen()10070b57cec5SDimitry Andric     void onLParen() {
10080b57cec5SDimitry Andric       IntelExprState CurrState = State;
10090b57cec5SDimitry Andric       switch (State) {
10100b57cec5SDimitry Andric       default:
10110b57cec5SDimitry Andric         State = IES_ERROR;
10120b57cec5SDimitry Andric         break;
10130b57cec5SDimitry Andric       case IES_PLUS:
10140b57cec5SDimitry Andric       case IES_MINUS:
10150b57cec5SDimitry Andric       case IES_NOT:
10160b57cec5SDimitry Andric       case IES_OR:
10170b57cec5SDimitry Andric       case IES_XOR:
10180b57cec5SDimitry Andric       case IES_AND:
1019e8d8bef9SDimitry Andric       case IES_EQ:
1020e8d8bef9SDimitry Andric       case IES_NE:
1021e8d8bef9SDimitry Andric       case IES_LT:
1022e8d8bef9SDimitry Andric       case IES_LE:
1023e8d8bef9SDimitry Andric       case IES_GT:
1024e8d8bef9SDimitry Andric       case IES_GE:
10250b57cec5SDimitry Andric       case IES_LSHIFT:
10260b57cec5SDimitry Andric       case IES_RSHIFT:
10270b57cec5SDimitry Andric       case IES_MULTIPLY:
10280b57cec5SDimitry Andric       case IES_DIVIDE:
10290b57cec5SDimitry Andric       case IES_MOD:
10300b57cec5SDimitry Andric       case IES_LPAREN:
10310b57cec5SDimitry Andric       case IES_INIT:
10320b57cec5SDimitry Andric       case IES_LBRAC:
10330b57cec5SDimitry Andric         State = IES_LPAREN;
10340b57cec5SDimitry Andric         IC.pushOperator(IC_LPAREN);
10350b57cec5SDimitry Andric         break;
10360b57cec5SDimitry Andric       }
10370b57cec5SDimitry Andric       PrevState = CurrState;
10380b57cec5SDimitry Andric     }
onRParen()10390b57cec5SDimitry Andric     void onRParen() {
10400b57cec5SDimitry Andric       PrevState = State;
10410b57cec5SDimitry Andric       switch (State) {
10420b57cec5SDimitry Andric       default:
10430b57cec5SDimitry Andric         State = IES_ERROR;
10440b57cec5SDimitry Andric         break;
10450b57cec5SDimitry Andric       case IES_INTEGER:
1046480093f4SDimitry Andric       case IES_OFFSET:
10470b57cec5SDimitry Andric       case IES_REGISTER:
10485ffd83dbSDimitry Andric       case IES_RBRAC:
10490b57cec5SDimitry Andric       case IES_RPAREN:
10500b57cec5SDimitry Andric         State = IES_RPAREN;
10510b57cec5SDimitry Andric         IC.pushOperator(IC_RPAREN);
10520b57cec5SDimitry Andric         break;
10530b57cec5SDimitry Andric       }
10540b57cec5SDimitry Andric     }
onOffset(const MCExpr * Val,SMLoc OffsetLoc,StringRef ID,const InlineAsmIdentifierInfo & IDInfo,bool ParsingMSInlineAsm,StringRef & ErrMsg)1055480093f4SDimitry Andric     bool onOffset(const MCExpr *Val, SMLoc OffsetLoc, StringRef ID,
1056e8d8bef9SDimitry Andric                   const InlineAsmIdentifierInfo &IDInfo,
1057e8d8bef9SDimitry Andric                   bool ParsingMSInlineAsm, StringRef &ErrMsg) {
1058480093f4SDimitry Andric       PrevState = State;
1059480093f4SDimitry Andric       switch (State) {
1060480093f4SDimitry Andric       default:
1061480093f4SDimitry Andric         ErrMsg = "unexpected offset operator expression";
1062480093f4SDimitry Andric         return true;
1063480093f4SDimitry Andric       case IES_PLUS:
1064480093f4SDimitry Andric       case IES_INIT:
1065480093f4SDimitry Andric       case IES_LBRAC:
1066480093f4SDimitry Andric         if (setSymRef(Val, ID, ErrMsg))
1067480093f4SDimitry Andric           return true;
1068480093f4SDimitry Andric         OffsetOperator = true;
1069480093f4SDimitry Andric         OffsetOperatorLoc = OffsetLoc;
1070480093f4SDimitry Andric         State = IES_OFFSET;
1071480093f4SDimitry Andric         // As we cannot yet resolve the actual value (offset), we retain
1072480093f4SDimitry Andric         // the requested semantics by pushing a '0' to the operands stack
1073480093f4SDimitry Andric         IC.pushOperand(IC_IMM);
10745ffd83dbSDimitry Andric         if (ParsingMSInlineAsm) {
1075480093f4SDimitry Andric           Info = IDInfo;
1076480093f4SDimitry Andric         }
1077480093f4SDimitry Andric         break;
1078480093f4SDimitry Andric       }
1079480093f4SDimitry Andric       return false;
1080480093f4SDimitry Andric     }
onCast(AsmTypeInfo Info)1081e8d8bef9SDimitry Andric     void onCast(AsmTypeInfo Info) {
10825ffd83dbSDimitry Andric       PrevState = State;
10835ffd83dbSDimitry Andric       switch (State) {
10845ffd83dbSDimitry Andric       default:
10855ffd83dbSDimitry Andric         State = IES_ERROR;
10865ffd83dbSDimitry Andric         break;
10875ffd83dbSDimitry Andric       case IES_LPAREN:
1088e8d8bef9SDimitry Andric         setTypeInfo(Info);
10895ffd83dbSDimitry Andric         State = IES_CAST;
10905ffd83dbSDimitry Andric         break;
10915ffd83dbSDimitry Andric       }
10925ffd83dbSDimitry Andric     }
setTypeInfo(AsmTypeInfo Type)1093e8d8bef9SDimitry Andric     void setTypeInfo(AsmTypeInfo Type) { CurType = Type; }
10940b57cec5SDimitry Andric   };
10950b57cec5SDimitry Andric 
Error(SMLoc L,const Twine & Msg,SMRange Range=std::nullopt,bool MatchingInlineAsm=false)1096bdd1243dSDimitry Andric   bool Error(SMLoc L, const Twine &Msg, SMRange Range = std::nullopt,
10970b57cec5SDimitry Andric              bool MatchingInlineAsm = false) {
10980b57cec5SDimitry Andric     MCAsmParser &Parser = getParser();
10990b57cec5SDimitry Andric     if (MatchingInlineAsm) {
11000b57cec5SDimitry Andric       if (!getLexer().isAtStartOfStatement())
11010b57cec5SDimitry Andric         Parser.eatToEndOfStatement();
11020b57cec5SDimitry Andric       return false;
11030b57cec5SDimitry Andric     }
11040b57cec5SDimitry Andric     return Parser.Error(L, Msg, Range);
11050b57cec5SDimitry Andric   }
11060b57cec5SDimitry Andric 
1107bdd1243dSDimitry Andric   bool MatchRegisterByName(MCRegister &RegNo, StringRef RegName, SMLoc StartLoc,
11085ffd83dbSDimitry Andric                            SMLoc EndLoc);
1109bdd1243dSDimitry Andric   bool ParseRegister(MCRegister &RegNo, SMLoc &StartLoc, SMLoc &EndLoc,
11105ffd83dbSDimitry Andric                      bool RestoreOnFailure);
11115ffd83dbSDimitry Andric 
11120b57cec5SDimitry Andric   std::unique_ptr<X86Operand> DefaultMemSIOperand(SMLoc Loc);
11130b57cec5SDimitry Andric   std::unique_ptr<X86Operand> DefaultMemDIOperand(SMLoc Loc);
11140b57cec5SDimitry Andric   bool IsSIReg(unsigned Reg);
11150b57cec5SDimitry Andric   unsigned GetSIDIForRegClass(unsigned RegClassID, unsigned Reg, bool IsSIReg);
11160b57cec5SDimitry Andric   void
11170b57cec5SDimitry Andric   AddDefaultSrcDestOperands(OperandVector &Operands,
11180b57cec5SDimitry Andric                             std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,
11190b57cec5SDimitry Andric                             std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst);
11200b57cec5SDimitry Andric   bool VerifyAndAdjustOperands(OperandVector &OrigOperands,
11210b57cec5SDimitry Andric                                OperandVector &FinalOperands);
112281ad6265SDimitry Andric   bool parseOperand(OperandVector &Operands, StringRef Name);
112381ad6265SDimitry Andric   bool parseATTOperand(OperandVector &Operands);
112481ad6265SDimitry Andric   bool parseIntelOperand(OperandVector &Operands, StringRef Name);
1125480093f4SDimitry Andric   bool ParseIntelOffsetOperator(const MCExpr *&Val, StringRef &ID,
1126480093f4SDimitry Andric                                 InlineAsmIdentifierInfo &Info, SMLoc &End);
11270b57cec5SDimitry Andric   bool ParseIntelDotOperator(IntelExprStateMachine &SM, SMLoc &End);
11280b57cec5SDimitry Andric   unsigned IdentifyIntelInlineAsmOperator(StringRef Name);
11290b57cec5SDimitry Andric   unsigned ParseIntelInlineAsmOperator(unsigned OpKind);
1130e8d8bef9SDimitry Andric   unsigned IdentifyMasmOperator(StringRef Name);
1131e8d8bef9SDimitry Andric   bool ParseMasmOperator(unsigned OpKind, int64_t &Val);
1132e8d8bef9SDimitry Andric   bool ParseRoundingModeOp(SMLoc Start, OperandVector &Operands);
11330fca6ea1SDimitry Andric   bool parseCFlagsOp(OperandVector &Operands);
1134480093f4SDimitry Andric   bool ParseIntelNamedOperator(StringRef Name, IntelExprStateMachine &SM,
1135480093f4SDimitry Andric                                bool &ParseError, SMLoc &End);
1136e8d8bef9SDimitry Andric   bool ParseMasmNamedOperator(StringRef Name, IntelExprStateMachine &SM,
1137e8d8bef9SDimitry Andric                               bool &ParseError, SMLoc &End);
11380b57cec5SDimitry Andric   void RewriteIntelExpression(IntelExprStateMachine &SM, SMLoc Start,
11390b57cec5SDimitry Andric                               SMLoc End);
11400b57cec5SDimitry Andric   bool ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End);
11410b57cec5SDimitry Andric   bool ParseIntelInlineAsmIdentifier(const MCExpr *&Val, StringRef &Identifier,
11420b57cec5SDimitry Andric                                      InlineAsmIdentifierInfo &Info,
1143480093f4SDimitry Andric                                      bool IsUnevaluatedOperand, SMLoc &End,
1144480093f4SDimitry Andric                                      bool IsParsingOffsetOperator = false);
114581ad6265SDimitry Andric   void tryParseOperandIdx(AsmToken::TokenKind PrevTK,
114681ad6265SDimitry Andric                           IntelExprStateMachine &SM);
11470b57cec5SDimitry Andric 
1148e8d8bef9SDimitry Andric   bool ParseMemOperand(unsigned SegReg, const MCExpr *Disp, SMLoc StartLoc,
1149e8d8bef9SDimitry Andric                        SMLoc EndLoc, OperandVector &Operands);
11500b57cec5SDimitry Andric 
11510b57cec5SDimitry Andric   X86::CondCode ParseConditionCode(StringRef CCode);
11520b57cec5SDimitry Andric 
11530b57cec5SDimitry Andric   bool ParseIntelMemoryOperandSize(unsigned &Size);
1154e8d8bef9SDimitry Andric   bool CreateMemForMSInlineAsm(unsigned SegReg, const MCExpr *Disp,
1155e8d8bef9SDimitry Andric                                unsigned BaseReg, unsigned IndexReg,
11565f757f3fSDimitry Andric                                unsigned Scale, bool NonAbsMem, SMLoc Start,
11575f757f3fSDimitry Andric                                SMLoc End, unsigned Size, StringRef Identifier,
1158e8d8bef9SDimitry Andric                                const InlineAsmIdentifierInfo &Info,
1159e8d8bef9SDimitry Andric                                OperandVector &Operands);
11600b57cec5SDimitry Andric 
1161e8d8bef9SDimitry Andric   bool parseDirectiveArch();
1162e8d8bef9SDimitry Andric   bool parseDirectiveNops(SMLoc L);
11630b57cec5SDimitry Andric   bool parseDirectiveEven(SMLoc L);
11640b57cec5SDimitry Andric   bool ParseDirectiveCode(StringRef IDVal, SMLoc L);
11650b57cec5SDimitry Andric 
11660b57cec5SDimitry Andric   /// CodeView FPO data directives.
11670b57cec5SDimitry Andric   bool parseDirectiveFPOProc(SMLoc L);
11680b57cec5SDimitry Andric   bool parseDirectiveFPOSetFrame(SMLoc L);
11690b57cec5SDimitry Andric   bool parseDirectiveFPOPushReg(SMLoc L);
11700b57cec5SDimitry Andric   bool parseDirectiveFPOStackAlloc(SMLoc L);
11710b57cec5SDimitry Andric   bool parseDirectiveFPOStackAlign(SMLoc L);
11720b57cec5SDimitry Andric   bool parseDirectiveFPOEndPrologue(SMLoc L);
11730b57cec5SDimitry Andric   bool parseDirectiveFPOEndProc(SMLoc L);
11740b57cec5SDimitry Andric 
11758bcb0991SDimitry Andric   /// SEH directives.
1176bdd1243dSDimitry Andric   bool parseSEHRegisterNumber(unsigned RegClassID, MCRegister &RegNo);
11778bcb0991SDimitry Andric   bool parseDirectiveSEHPushReg(SMLoc);
11788bcb0991SDimitry Andric   bool parseDirectiveSEHSetFrame(SMLoc);
11798bcb0991SDimitry Andric   bool parseDirectiveSEHSaveReg(SMLoc);
11808bcb0991SDimitry Andric   bool parseDirectiveSEHSaveXMM(SMLoc);
11818bcb0991SDimitry Andric   bool parseDirectiveSEHPushFrame(SMLoc);
11828bcb0991SDimitry Andric 
11830b57cec5SDimitry Andric   unsigned checkTargetMatchPredicate(MCInst &Inst) override;
11840b57cec5SDimitry Andric 
11850b57cec5SDimitry Andric   bool validateInstruction(MCInst &Inst, const OperandVector &Ops);
11860b57cec5SDimitry Andric   bool processInstruction(MCInst &Inst, const OperandVector &Ops);
11870b57cec5SDimitry Andric 
11885ffd83dbSDimitry Andric   // Load Value Injection (LVI) Mitigations for machine code
11895ffd83dbSDimitry Andric   void emitWarningForSpecialLVIInstruction(SMLoc Loc);
11905ffd83dbSDimitry Andric   void applyLVICFIMitigation(MCInst &Inst, MCStreamer &Out);
11915ffd83dbSDimitry Andric   void applyLVILoadHardeningMitigation(MCInst &Inst, MCStreamer &Out);
11925ffd83dbSDimitry Andric 
11935ffd83dbSDimitry Andric   /// Wrapper around MCStreamer::emitInstruction(). Possibly adds
11940b57cec5SDimitry Andric   /// instrumentation around Inst.
11955ffd83dbSDimitry Andric   void emitInstruction(MCInst &Inst, OperandVector &Operands, MCStreamer &Out);
11960b57cec5SDimitry Andric 
11970b57cec5SDimitry Andric   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
11980b57cec5SDimitry Andric                                OperandVector &Operands, MCStreamer &Out,
11990b57cec5SDimitry Andric                                uint64_t &ErrorInfo,
12000b57cec5SDimitry Andric                                bool MatchingInlineAsm) override;
12010b57cec5SDimitry Andric 
12020b57cec5SDimitry Andric   void MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op, OperandVector &Operands,
12030b57cec5SDimitry Andric                          MCStreamer &Out, bool MatchingInlineAsm);
12040b57cec5SDimitry Andric 
12050b57cec5SDimitry Andric   bool ErrorMissingFeature(SMLoc IDLoc, const FeatureBitset &MissingFeatures,
12060b57cec5SDimitry Andric                            bool MatchingInlineAsm);
12070b57cec5SDimitry Andric 
12080fca6ea1SDimitry Andric   bool matchAndEmitATTInstruction(SMLoc IDLoc, unsigned &Opcode, MCInst &Inst,
12090b57cec5SDimitry Andric                                   OperandVector &Operands, MCStreamer &Out,
12100fca6ea1SDimitry Andric                                   uint64_t &ErrorInfo, bool MatchingInlineAsm);
12110b57cec5SDimitry Andric 
12120fca6ea1SDimitry Andric   bool matchAndEmitIntelInstruction(SMLoc IDLoc, unsigned &Opcode, MCInst &Inst,
12130b57cec5SDimitry Andric                                     OperandVector &Operands, MCStreamer &Out,
12140b57cec5SDimitry Andric                                     uint64_t &ErrorInfo,
12150b57cec5SDimitry Andric                                     bool MatchingInlineAsm);
12160b57cec5SDimitry Andric 
12170b57cec5SDimitry Andric   bool OmitRegisterFromClobberLists(unsigned RegNo) override;
12180b57cec5SDimitry Andric 
12190b57cec5SDimitry Andric   /// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z})
12200b57cec5SDimitry Andric   /// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required.
12210b57cec5SDimitry Andric   /// return false if no parsing errors occurred, true otherwise.
1222e8d8bef9SDimitry Andric   bool HandleAVX512Operand(OperandVector &Operands);
12230b57cec5SDimitry Andric 
12240b57cec5SDimitry Andric   bool ParseZ(std::unique_ptr<X86Operand> &Z, const SMLoc &StartLoc);
12250b57cec5SDimitry Andric 
is64BitMode() const12260b57cec5SDimitry Andric   bool is64BitMode() const {
12270b57cec5SDimitry Andric     // FIXME: Can tablegen auto-generate this?
122806c3fb27SDimitry Andric     return getSTI().hasFeature(X86::Is64Bit);
12290b57cec5SDimitry Andric   }
is32BitMode() const12300b57cec5SDimitry Andric   bool is32BitMode() const {
12310b57cec5SDimitry Andric     // FIXME: Can tablegen auto-generate this?
123206c3fb27SDimitry Andric     return getSTI().hasFeature(X86::Is32Bit);
12330b57cec5SDimitry Andric   }
is16BitMode() const12340b57cec5SDimitry Andric   bool is16BitMode() const {
12350b57cec5SDimitry Andric     // FIXME: Can tablegen auto-generate this?
123606c3fb27SDimitry Andric     return getSTI().hasFeature(X86::Is16Bit);
12370b57cec5SDimitry Andric   }
SwitchMode(unsigned mode)12380b57cec5SDimitry Andric   void SwitchMode(unsigned mode) {
12390b57cec5SDimitry Andric     MCSubtargetInfo &STI = copySTI();
124081ad6265SDimitry Andric     FeatureBitset AllModes({X86::Is64Bit, X86::Is32Bit, X86::Is16Bit});
12410b57cec5SDimitry Andric     FeatureBitset OldMode = STI.getFeatureBits() & AllModes;
12420b57cec5SDimitry Andric     FeatureBitset FB = ComputeAvailableFeatures(
12430b57cec5SDimitry Andric       STI.ToggleFeature(OldMode.flip(mode)));
12440b57cec5SDimitry Andric     setAvailableFeatures(FB);
12450b57cec5SDimitry Andric 
12460b57cec5SDimitry Andric     assert(FeatureBitset({mode}) == (STI.getFeatureBits() & AllModes));
12470b57cec5SDimitry Andric   }
12480b57cec5SDimitry Andric 
getPointerWidth()12490b57cec5SDimitry Andric   unsigned getPointerWidth() {
12500b57cec5SDimitry Andric     if (is16BitMode()) return 16;
12510b57cec5SDimitry Andric     if (is32BitMode()) return 32;
12520b57cec5SDimitry Andric     if (is64BitMode()) return 64;
12530b57cec5SDimitry Andric     llvm_unreachable("invalid mode");
12540b57cec5SDimitry Andric   }
12550b57cec5SDimitry Andric 
isParsingIntelSyntax()12560b57cec5SDimitry Andric   bool isParsingIntelSyntax() {
12570b57cec5SDimitry Andric     return getParser().getAssemblerDialect();
12580b57cec5SDimitry Andric   }
12590b57cec5SDimitry Andric 
12600b57cec5SDimitry Andric   /// @name Auto-generated Matcher Functions
12610b57cec5SDimitry Andric   /// {
12620b57cec5SDimitry Andric 
12630b57cec5SDimitry Andric #define GET_ASSEMBLER_HEADER
12640b57cec5SDimitry Andric #include "X86GenAsmMatcher.inc"
12650b57cec5SDimitry Andric 
12660b57cec5SDimitry Andric   /// }
12670b57cec5SDimitry Andric 
12680b57cec5SDimitry Andric public:
12690b57cec5SDimitry Andric   enum X86MatchResultTy {
12700b57cec5SDimitry Andric     Match_Unsupported = FIRST_TARGET_MATCH_RESULT_TY,
12718bcb0991SDimitry Andric #define GET_OPERAND_DIAGNOSTIC_TYPES
12728bcb0991SDimitry Andric #include "X86GenAsmMatcher.inc"
12730b57cec5SDimitry Andric   };
12740b57cec5SDimitry Andric 
X86AsmParser(const MCSubtargetInfo & sti,MCAsmParser & Parser,const MCInstrInfo & mii,const MCTargetOptions & Options)12750b57cec5SDimitry Andric   X86AsmParser(const MCSubtargetInfo &sti, MCAsmParser &Parser,
12760b57cec5SDimitry Andric                const MCInstrInfo &mii, const MCTargetOptions &Options)
12770b57cec5SDimitry Andric       : MCTargetAsmParser(Options, sti, mii),  InstInfo(nullptr),
12780b57cec5SDimitry Andric         Code16GCC(false) {
12790b57cec5SDimitry Andric 
12800b57cec5SDimitry Andric     Parser.addAliasForDirective(".word", ".2byte");
12810b57cec5SDimitry Andric 
12820b57cec5SDimitry Andric     // Initialize the set of available features.
12830b57cec5SDimitry Andric     setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
12840b57cec5SDimitry Andric   }
12850b57cec5SDimitry Andric 
12865f757f3fSDimitry Andric   bool parseRegister(MCRegister &Reg, SMLoc &StartLoc, SMLoc &EndLoc) override;
12875f757f3fSDimitry Andric   ParseStatus tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
12885ffd83dbSDimitry Andric                                SMLoc &EndLoc) override;
12890b57cec5SDimitry Andric 
12900b57cec5SDimitry Andric   bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
12910b57cec5SDimitry Andric 
12920b57cec5SDimitry Andric   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
12930b57cec5SDimitry Andric                         SMLoc NameLoc, OperandVector &Operands) override;
12940b57cec5SDimitry Andric 
12950b57cec5SDimitry Andric   bool ParseDirective(AsmToken DirectiveID) override;
12960b57cec5SDimitry Andric };
12970b57cec5SDimitry Andric } // end anonymous namespace
12980b57cec5SDimitry Andric 
129906c3fb27SDimitry Andric #define GET_REGISTER_MATCHER
130006c3fb27SDimitry Andric #define GET_SUBTARGET_FEATURE_NAME
130106c3fb27SDimitry Andric #include "X86GenAsmMatcher.inc"
13020b57cec5SDimitry Andric 
CheckBaseRegAndIndexRegAndScale(unsigned BaseReg,unsigned IndexReg,unsigned Scale,bool Is64BitMode,StringRef & ErrMsg)13030b57cec5SDimitry Andric static bool CheckBaseRegAndIndexRegAndScale(unsigned BaseReg, unsigned IndexReg,
13040b57cec5SDimitry Andric                                             unsigned Scale, bool Is64BitMode,
13050b57cec5SDimitry Andric                                             StringRef &ErrMsg) {
13060b57cec5SDimitry Andric   // If we have both a base register and an index register make sure they are
13070b57cec5SDimitry Andric   // both 64-bit or 32-bit registers.
13080b57cec5SDimitry Andric   // To support VSIB, IndexReg can be 128-bit or 256-bit registers.
13090b57cec5SDimitry Andric 
13100b57cec5SDimitry Andric   if (BaseReg != 0 &&
13110b57cec5SDimitry Andric       !(BaseReg == X86::RIP || BaseReg == X86::EIP ||
13120b57cec5SDimitry Andric         X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) ||
13130b57cec5SDimitry Andric         X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) ||
13140b57cec5SDimitry Andric         X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg))) {
13150b57cec5SDimitry Andric     ErrMsg = "invalid base+index expression";
13160b57cec5SDimitry Andric     return true;
13170b57cec5SDimitry Andric   }
13180b57cec5SDimitry Andric 
13190b57cec5SDimitry Andric   if (IndexReg != 0 &&
13200b57cec5SDimitry Andric       !(IndexReg == X86::EIZ || IndexReg == X86::RIZ ||
13210b57cec5SDimitry Andric         X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
13220b57cec5SDimitry Andric         X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
13230b57cec5SDimitry Andric         X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg) ||
13240b57cec5SDimitry Andric         X86MCRegisterClasses[X86::VR128XRegClassID].contains(IndexReg) ||
13250b57cec5SDimitry Andric         X86MCRegisterClasses[X86::VR256XRegClassID].contains(IndexReg) ||
13260b57cec5SDimitry Andric         X86MCRegisterClasses[X86::VR512RegClassID].contains(IndexReg))) {
13270b57cec5SDimitry Andric     ErrMsg = "invalid base+index expression";
13280b57cec5SDimitry Andric     return true;
13290b57cec5SDimitry Andric   }
13300b57cec5SDimitry Andric 
13310b57cec5SDimitry Andric   if (((BaseReg == X86::RIP || BaseReg == X86::EIP) && IndexReg != 0) ||
13320b57cec5SDimitry Andric       IndexReg == X86::EIP || IndexReg == X86::RIP ||
13330b57cec5SDimitry Andric       IndexReg == X86::ESP || IndexReg == X86::RSP) {
13340b57cec5SDimitry Andric     ErrMsg = "invalid base+index expression";
13350b57cec5SDimitry Andric     return true;
13360b57cec5SDimitry Andric   }
13370b57cec5SDimitry Andric 
13380b57cec5SDimitry Andric   // Check for use of invalid 16-bit registers. Only BX/BP/SI/DI are allowed,
13390b57cec5SDimitry Andric   // and then only in non-64-bit modes.
13400b57cec5SDimitry Andric   if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
13410b57cec5SDimitry Andric       (Is64BitMode || (BaseReg != X86::BX && BaseReg != X86::BP &&
13420b57cec5SDimitry Andric                        BaseReg != X86::SI && BaseReg != X86::DI))) {
13430b57cec5SDimitry Andric     ErrMsg = "invalid 16-bit base register";
13440b57cec5SDimitry Andric     return true;
13450b57cec5SDimitry Andric   }
13460b57cec5SDimitry Andric 
13470b57cec5SDimitry Andric   if (BaseReg == 0 &&
13480b57cec5SDimitry Andric       X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg)) {
13490b57cec5SDimitry Andric     ErrMsg = "16-bit memory operand may not include only index register";
13500b57cec5SDimitry Andric     return true;
13510b57cec5SDimitry Andric   }
13520b57cec5SDimitry Andric 
13530b57cec5SDimitry Andric   if (BaseReg != 0 && IndexReg != 0) {
13540b57cec5SDimitry Andric     if (X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg) &&
13550b57cec5SDimitry Andric         (X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
13560b57cec5SDimitry Andric          X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
13570b57cec5SDimitry Andric          IndexReg == X86::EIZ)) {
13580b57cec5SDimitry Andric       ErrMsg = "base register is 64-bit, but index register is not";
13590b57cec5SDimitry Andric       return true;
13600b57cec5SDimitry Andric     }
13610b57cec5SDimitry Andric     if (X86MCRegisterClasses[X86::GR32RegClassID].contains(BaseReg) &&
13620b57cec5SDimitry Andric         (X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg) ||
13630b57cec5SDimitry Andric          X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg) ||
13640b57cec5SDimitry Andric          IndexReg == X86::RIZ)) {
13650b57cec5SDimitry Andric       ErrMsg = "base register is 32-bit, but index register is not";
13660b57cec5SDimitry Andric       return true;
13670b57cec5SDimitry Andric     }
13680b57cec5SDimitry Andric     if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg)) {
13690b57cec5SDimitry Andric       if (X86MCRegisterClasses[X86::GR32RegClassID].contains(IndexReg) ||
13700b57cec5SDimitry Andric           X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg)) {
13710b57cec5SDimitry Andric         ErrMsg = "base register is 16-bit, but index register is not";
13720b57cec5SDimitry Andric         return true;
13730b57cec5SDimitry Andric       }
13740b57cec5SDimitry Andric       if ((BaseReg != X86::BX && BaseReg != X86::BP) ||
13750b57cec5SDimitry Andric           (IndexReg != X86::SI && IndexReg != X86::DI)) {
13760b57cec5SDimitry Andric         ErrMsg = "invalid 16-bit base/index register combination";
13770b57cec5SDimitry Andric         return true;
13780b57cec5SDimitry Andric       }
13790b57cec5SDimitry Andric     }
13800b57cec5SDimitry Andric   }
13810b57cec5SDimitry Andric 
13820b57cec5SDimitry Andric   // RIP/EIP-relative addressing is only supported in 64-bit mode.
13830b57cec5SDimitry Andric   if (!Is64BitMode && BaseReg != 0 &&
13840b57cec5SDimitry Andric       (BaseReg == X86::RIP || BaseReg == X86::EIP)) {
13850b57cec5SDimitry Andric     ErrMsg = "IP-relative addressing requires 64-bit mode";
13860b57cec5SDimitry Andric     return true;
13870b57cec5SDimitry Andric   }
13880b57cec5SDimitry Andric 
13890b57cec5SDimitry Andric   return checkScale(Scale, ErrMsg);
13900b57cec5SDimitry Andric }
13910b57cec5SDimitry Andric 
MatchRegisterByName(MCRegister & RegNo,StringRef RegName,SMLoc StartLoc,SMLoc EndLoc)1392bdd1243dSDimitry Andric bool X86AsmParser::MatchRegisterByName(MCRegister &RegNo, StringRef RegName,
13935ffd83dbSDimitry Andric                                        SMLoc StartLoc, SMLoc EndLoc) {
13940b57cec5SDimitry Andric   // If we encounter a %, ignore it. This code handles registers with and
13950b57cec5SDimitry Andric   // without the prefix, unprefixed registers can occur in cfi directives.
13965ffd83dbSDimitry Andric   RegName.consume_front("%");
13970b57cec5SDimitry Andric 
13985ffd83dbSDimitry Andric   RegNo = MatchRegisterName(RegName);
13990b57cec5SDimitry Andric 
14000b57cec5SDimitry Andric   // If the match failed, try the register name as lowercase.
14010b57cec5SDimitry Andric   if (RegNo == 0)
14025ffd83dbSDimitry Andric     RegNo = MatchRegisterName(RegName.lower());
14030b57cec5SDimitry Andric 
1404480093f4SDimitry Andric   // The "flags" and "mxcsr" registers cannot be referenced directly.
14050b57cec5SDimitry Andric   // Treat it as an identifier instead.
14065ffd83dbSDimitry Andric   if (isParsingMSInlineAsm() && isParsingIntelSyntax() &&
1407480093f4SDimitry Andric       (RegNo == X86::EFLAGS || RegNo == X86::MXCSR))
14080b57cec5SDimitry Andric     RegNo = 0;
14090b57cec5SDimitry Andric 
14100b57cec5SDimitry Andric   if (!is64BitMode()) {
14110b57cec5SDimitry Andric     // FIXME: This should be done using Requires<Not64BitMode> and
14120b57cec5SDimitry Andric     // Requires<In64BitMode> so "eiz" usage in 64-bit instructions can be also
14130b57cec5SDimitry Andric     // checked.
14140b57cec5SDimitry Andric     if (RegNo == X86::RIZ || RegNo == X86::RIP ||
14150b57cec5SDimitry Andric         X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo) ||
14160b57cec5SDimitry Andric         X86II::isX86_64NonExtLowByteReg(RegNo) ||
14170b57cec5SDimitry Andric         X86II::isX86_64ExtendedReg(RegNo)) {
14180b57cec5SDimitry Andric       return Error(StartLoc,
14190b57cec5SDimitry Andric                    "register %" + RegName + " is only available in 64-bit mode",
14200b57cec5SDimitry Andric                    SMRange(StartLoc, EndLoc));
14210b57cec5SDimitry Andric     }
14220b57cec5SDimitry Andric   }
14230b57cec5SDimitry Andric 
14245f757f3fSDimitry Andric   if (X86II::isApxExtendedReg(RegNo))
14255f757f3fSDimitry Andric     UseApxExtendedReg = true;
14265f757f3fSDimitry Andric 
14275ffd83dbSDimitry Andric   // If this is "db[0-15]", match it as an alias
14285ffd83dbSDimitry Andric   // for dr[0-15].
14295f757f3fSDimitry Andric   if (RegNo == 0 && RegName.starts_with("db")) {
14305ffd83dbSDimitry Andric     if (RegName.size() == 3) {
14315ffd83dbSDimitry Andric       switch (RegName[2]) {
14325ffd83dbSDimitry Andric       case '0':
14335ffd83dbSDimitry Andric         RegNo = X86::DR0;
14345ffd83dbSDimitry Andric         break;
14355ffd83dbSDimitry Andric       case '1':
14365ffd83dbSDimitry Andric         RegNo = X86::DR1;
14375ffd83dbSDimitry Andric         break;
14385ffd83dbSDimitry Andric       case '2':
14395ffd83dbSDimitry Andric         RegNo = X86::DR2;
14405ffd83dbSDimitry Andric         break;
14415ffd83dbSDimitry Andric       case '3':
14425ffd83dbSDimitry Andric         RegNo = X86::DR3;
14435ffd83dbSDimitry Andric         break;
14445ffd83dbSDimitry Andric       case '4':
14455ffd83dbSDimitry Andric         RegNo = X86::DR4;
14465ffd83dbSDimitry Andric         break;
14475ffd83dbSDimitry Andric       case '5':
14485ffd83dbSDimitry Andric         RegNo = X86::DR5;
14495ffd83dbSDimitry Andric         break;
14505ffd83dbSDimitry Andric       case '6':
14515ffd83dbSDimitry Andric         RegNo = X86::DR6;
14525ffd83dbSDimitry Andric         break;
14535ffd83dbSDimitry Andric       case '7':
14545ffd83dbSDimitry Andric         RegNo = X86::DR7;
14555ffd83dbSDimitry Andric         break;
14565ffd83dbSDimitry Andric       case '8':
14575ffd83dbSDimitry Andric         RegNo = X86::DR8;
14585ffd83dbSDimitry Andric         break;
14595ffd83dbSDimitry Andric       case '9':
14605ffd83dbSDimitry Andric         RegNo = X86::DR9;
14615ffd83dbSDimitry Andric         break;
14625ffd83dbSDimitry Andric       }
14635ffd83dbSDimitry Andric     } else if (RegName.size() == 4 && RegName[2] == '1') {
14645ffd83dbSDimitry Andric       switch (RegName[3]) {
14655ffd83dbSDimitry Andric       case '0':
14665ffd83dbSDimitry Andric         RegNo = X86::DR10;
14675ffd83dbSDimitry Andric         break;
14685ffd83dbSDimitry Andric       case '1':
14695ffd83dbSDimitry Andric         RegNo = X86::DR11;
14705ffd83dbSDimitry Andric         break;
14715ffd83dbSDimitry Andric       case '2':
14725ffd83dbSDimitry Andric         RegNo = X86::DR12;
14735ffd83dbSDimitry Andric         break;
14745ffd83dbSDimitry Andric       case '3':
14755ffd83dbSDimitry Andric         RegNo = X86::DR13;
14765ffd83dbSDimitry Andric         break;
14775ffd83dbSDimitry Andric       case '4':
14785ffd83dbSDimitry Andric         RegNo = X86::DR14;
14795ffd83dbSDimitry Andric         break;
14805ffd83dbSDimitry Andric       case '5':
14815ffd83dbSDimitry Andric         RegNo = X86::DR15;
14825ffd83dbSDimitry Andric         break;
14835ffd83dbSDimitry Andric       }
14845ffd83dbSDimitry Andric     }
14855ffd83dbSDimitry Andric   }
14865ffd83dbSDimitry Andric 
14875ffd83dbSDimitry Andric   if (RegNo == 0) {
14885ffd83dbSDimitry Andric     if (isParsingIntelSyntax())
14895ffd83dbSDimitry Andric       return true;
14905ffd83dbSDimitry Andric     return Error(StartLoc, "invalid register name", SMRange(StartLoc, EndLoc));
14915ffd83dbSDimitry Andric   }
14925ffd83dbSDimitry Andric   return false;
14935ffd83dbSDimitry Andric }
14945ffd83dbSDimitry Andric 
ParseRegister(MCRegister & RegNo,SMLoc & StartLoc,SMLoc & EndLoc,bool RestoreOnFailure)1495bdd1243dSDimitry Andric bool X86AsmParser::ParseRegister(MCRegister &RegNo, SMLoc &StartLoc,
14965ffd83dbSDimitry Andric                                  SMLoc &EndLoc, bool RestoreOnFailure) {
14975ffd83dbSDimitry Andric   MCAsmParser &Parser = getParser();
14985ffd83dbSDimitry Andric   MCAsmLexer &Lexer = getLexer();
14995ffd83dbSDimitry Andric   RegNo = 0;
15005ffd83dbSDimitry Andric 
15015ffd83dbSDimitry Andric   SmallVector<AsmToken, 5> Tokens;
15025ffd83dbSDimitry Andric   auto OnFailure = [RestoreOnFailure, &Lexer, &Tokens]() {
15035ffd83dbSDimitry Andric     if (RestoreOnFailure) {
15045ffd83dbSDimitry Andric       while (!Tokens.empty()) {
15055ffd83dbSDimitry Andric         Lexer.UnLex(Tokens.pop_back_val());
15065ffd83dbSDimitry Andric       }
15075ffd83dbSDimitry Andric     }
15085ffd83dbSDimitry Andric   };
15095ffd83dbSDimitry Andric 
15105ffd83dbSDimitry Andric   const AsmToken &PercentTok = Parser.getTok();
15115ffd83dbSDimitry Andric   StartLoc = PercentTok.getLoc();
15125ffd83dbSDimitry Andric 
15135ffd83dbSDimitry Andric   // If we encounter a %, ignore it. This code handles registers with and
15145ffd83dbSDimitry Andric   // without the prefix, unprefixed registers can occur in cfi directives.
15155ffd83dbSDimitry Andric   if (!isParsingIntelSyntax() && PercentTok.is(AsmToken::Percent)) {
15165ffd83dbSDimitry Andric     Tokens.push_back(PercentTok);
15175ffd83dbSDimitry Andric     Parser.Lex(); // Eat percent token.
15185ffd83dbSDimitry Andric   }
15195ffd83dbSDimitry Andric 
15205ffd83dbSDimitry Andric   const AsmToken &Tok = Parser.getTok();
15215ffd83dbSDimitry Andric   EndLoc = Tok.getEndLoc();
15225ffd83dbSDimitry Andric 
15235ffd83dbSDimitry Andric   if (Tok.isNot(AsmToken::Identifier)) {
15245ffd83dbSDimitry Andric     OnFailure();
15255ffd83dbSDimitry Andric     if (isParsingIntelSyntax()) return true;
15265ffd83dbSDimitry Andric     return Error(StartLoc, "invalid register name",
15275ffd83dbSDimitry Andric                  SMRange(StartLoc, EndLoc));
15285ffd83dbSDimitry Andric   }
15295ffd83dbSDimitry Andric 
15305ffd83dbSDimitry Andric   if (MatchRegisterByName(RegNo, Tok.getString(), StartLoc, EndLoc)) {
15315ffd83dbSDimitry Andric     OnFailure();
15325ffd83dbSDimitry Andric     return true;
15335ffd83dbSDimitry Andric   }
15345ffd83dbSDimitry Andric 
15350b57cec5SDimitry Andric   // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens.
15360b57cec5SDimitry Andric   if (RegNo == X86::ST0) {
15375ffd83dbSDimitry Andric     Tokens.push_back(Tok);
15380b57cec5SDimitry Andric     Parser.Lex(); // Eat 'st'
15390b57cec5SDimitry Andric 
15400b57cec5SDimitry Andric     // Check to see if we have '(4)' after %st.
15415ffd83dbSDimitry Andric     if (Lexer.isNot(AsmToken::LParen))
15420b57cec5SDimitry Andric       return false;
15430b57cec5SDimitry Andric     // Lex the paren.
15445ffd83dbSDimitry Andric     Tokens.push_back(Parser.getTok());
15455ffd83dbSDimitry Andric     Parser.Lex();
15460b57cec5SDimitry Andric 
15470b57cec5SDimitry Andric     const AsmToken &IntTok = Parser.getTok();
15485ffd83dbSDimitry Andric     if (IntTok.isNot(AsmToken::Integer)) {
15495ffd83dbSDimitry Andric       OnFailure();
15500b57cec5SDimitry Andric       return Error(IntTok.getLoc(), "expected stack index");
15515ffd83dbSDimitry Andric     }
15520b57cec5SDimitry Andric     switch (IntTok.getIntVal()) {
15530b57cec5SDimitry Andric     case 0: RegNo = X86::ST0; break;
15540b57cec5SDimitry Andric     case 1: RegNo = X86::ST1; break;
15550b57cec5SDimitry Andric     case 2: RegNo = X86::ST2; break;
15560b57cec5SDimitry Andric     case 3: RegNo = X86::ST3; break;
15570b57cec5SDimitry Andric     case 4: RegNo = X86::ST4; break;
15580b57cec5SDimitry Andric     case 5: RegNo = X86::ST5; break;
15590b57cec5SDimitry Andric     case 6: RegNo = X86::ST6; break;
15600b57cec5SDimitry Andric     case 7: RegNo = X86::ST7; break;
15615ffd83dbSDimitry Andric     default:
15625ffd83dbSDimitry Andric       OnFailure();
15635ffd83dbSDimitry Andric       return Error(IntTok.getLoc(), "invalid stack index");
15640b57cec5SDimitry Andric     }
15650b57cec5SDimitry Andric 
15665ffd83dbSDimitry Andric     // Lex IntTok
15675ffd83dbSDimitry Andric     Tokens.push_back(IntTok);
15685ffd83dbSDimitry Andric     Parser.Lex();
15695ffd83dbSDimitry Andric     if (Lexer.isNot(AsmToken::RParen)) {
15705ffd83dbSDimitry Andric       OnFailure();
15710b57cec5SDimitry Andric       return Error(Parser.getTok().getLoc(), "expected ')'");
15725ffd83dbSDimitry Andric     }
15730b57cec5SDimitry Andric 
15740b57cec5SDimitry Andric     EndLoc = Parser.getTok().getEndLoc();
15750b57cec5SDimitry Andric     Parser.Lex(); // Eat ')'
15760b57cec5SDimitry Andric     return false;
15770b57cec5SDimitry Andric   }
15780b57cec5SDimitry Andric 
15790b57cec5SDimitry Andric   EndLoc = Parser.getTok().getEndLoc();
15800b57cec5SDimitry Andric 
15810b57cec5SDimitry Andric   if (RegNo == 0) {
15825ffd83dbSDimitry Andric     OnFailure();
15830b57cec5SDimitry Andric     if (isParsingIntelSyntax()) return true;
15840b57cec5SDimitry Andric     return Error(StartLoc, "invalid register name",
15850b57cec5SDimitry Andric                  SMRange(StartLoc, EndLoc));
15860b57cec5SDimitry Andric   }
15870b57cec5SDimitry Andric 
15880b57cec5SDimitry Andric   Parser.Lex(); // Eat identifier token.
15890b57cec5SDimitry Andric   return false;
15900b57cec5SDimitry Andric }
15910b57cec5SDimitry Andric 
parseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)15925f757f3fSDimitry Andric bool X86AsmParser::parseRegister(MCRegister &Reg, SMLoc &StartLoc,
15935ffd83dbSDimitry Andric                                  SMLoc &EndLoc) {
15945f757f3fSDimitry Andric   return ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/false);
15955ffd83dbSDimitry Andric }
15965ffd83dbSDimitry Andric 
tryParseRegister(MCRegister & Reg,SMLoc & StartLoc,SMLoc & EndLoc)15975f757f3fSDimitry Andric ParseStatus X86AsmParser::tryParseRegister(MCRegister &Reg, SMLoc &StartLoc,
15985ffd83dbSDimitry Andric                                            SMLoc &EndLoc) {
15995f757f3fSDimitry Andric   bool Result = ParseRegister(Reg, StartLoc, EndLoc, /*RestoreOnFailure=*/true);
16005ffd83dbSDimitry Andric   bool PendingErrors = getParser().hasPendingError();
16015ffd83dbSDimitry Andric   getParser().clearPendingErrors();
16025ffd83dbSDimitry Andric   if (PendingErrors)
16035f757f3fSDimitry Andric     return ParseStatus::Failure;
16045ffd83dbSDimitry Andric   if (Result)
16055f757f3fSDimitry Andric     return ParseStatus::NoMatch;
16065f757f3fSDimitry Andric   return ParseStatus::Success;
16075ffd83dbSDimitry Andric }
16085ffd83dbSDimitry Andric 
DefaultMemSIOperand(SMLoc Loc)16090b57cec5SDimitry Andric std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
16100b57cec5SDimitry Andric   bool Parse32 = is32BitMode() || Code16GCC;
16110b57cec5SDimitry Andric   unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);
16120b57cec5SDimitry Andric   const MCExpr *Disp = MCConstantExpr::create(0, getContext());
16130b57cec5SDimitry Andric   return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
16140b57cec5SDimitry Andric                                /*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
16150b57cec5SDimitry Andric                                Loc, Loc, 0);
16160b57cec5SDimitry Andric }
16170b57cec5SDimitry Andric 
DefaultMemDIOperand(SMLoc Loc)16180b57cec5SDimitry Andric std::unique_ptr<X86Operand> X86AsmParser::DefaultMemDIOperand(SMLoc Loc) {
16190b57cec5SDimitry Andric   bool Parse32 = is32BitMode() || Code16GCC;
16200b57cec5SDimitry Andric   unsigned Basereg = is64BitMode() ? X86::RDI : (Parse32 ? X86::EDI : X86::DI);
16210b57cec5SDimitry Andric   const MCExpr *Disp = MCConstantExpr::create(0, getContext());
16220b57cec5SDimitry Andric   return X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
16230b57cec5SDimitry Andric                                /*BaseReg=*/Basereg, /*IndexReg=*/0, /*Scale=*/1,
16240b57cec5SDimitry Andric                                Loc, Loc, 0);
16250b57cec5SDimitry Andric }
16260b57cec5SDimitry Andric 
IsSIReg(unsigned Reg)16270b57cec5SDimitry Andric bool X86AsmParser::IsSIReg(unsigned Reg) {
16280b57cec5SDimitry Andric   switch (Reg) {
16290b57cec5SDimitry Andric   default: llvm_unreachable("Only (R|E)SI and (R|E)DI are expected!");
16300b57cec5SDimitry Andric   case X86::RSI:
16310b57cec5SDimitry Andric   case X86::ESI:
16320b57cec5SDimitry Andric   case X86::SI:
16330b57cec5SDimitry Andric     return true;
16340b57cec5SDimitry Andric   case X86::RDI:
16350b57cec5SDimitry Andric   case X86::EDI:
16360b57cec5SDimitry Andric   case X86::DI:
16370b57cec5SDimitry Andric     return false;
16380b57cec5SDimitry Andric   }
16390b57cec5SDimitry Andric }
16400b57cec5SDimitry Andric 
GetSIDIForRegClass(unsigned RegClassID,unsigned Reg,bool IsSIReg)16410b57cec5SDimitry Andric unsigned X86AsmParser::GetSIDIForRegClass(unsigned RegClassID, unsigned Reg,
16420b57cec5SDimitry Andric                                           bool IsSIReg) {
16430b57cec5SDimitry Andric   switch (RegClassID) {
16440b57cec5SDimitry Andric   default: llvm_unreachable("Unexpected register class");
16450b57cec5SDimitry Andric   case X86::GR64RegClassID:
16460b57cec5SDimitry Andric     return IsSIReg ? X86::RSI : X86::RDI;
16470b57cec5SDimitry Andric   case X86::GR32RegClassID:
16480b57cec5SDimitry Andric     return IsSIReg ? X86::ESI : X86::EDI;
16490b57cec5SDimitry Andric   case X86::GR16RegClassID:
16500b57cec5SDimitry Andric     return IsSIReg ? X86::SI : X86::DI;
16510b57cec5SDimitry Andric   }
16520b57cec5SDimitry Andric }
16530b57cec5SDimitry Andric 
AddDefaultSrcDestOperands(OperandVector & Operands,std::unique_ptr<llvm::MCParsedAsmOperand> && Src,std::unique_ptr<llvm::MCParsedAsmOperand> && Dst)16540b57cec5SDimitry Andric void X86AsmParser::AddDefaultSrcDestOperands(
16550b57cec5SDimitry Andric     OperandVector& Operands, std::unique_ptr<llvm::MCParsedAsmOperand> &&Src,
16560b57cec5SDimitry Andric     std::unique_ptr<llvm::MCParsedAsmOperand> &&Dst) {
16570b57cec5SDimitry Andric   if (isParsingIntelSyntax()) {
16580b57cec5SDimitry Andric     Operands.push_back(std::move(Dst));
16590b57cec5SDimitry Andric     Operands.push_back(std::move(Src));
16600b57cec5SDimitry Andric   }
16610b57cec5SDimitry Andric   else {
16620b57cec5SDimitry Andric     Operands.push_back(std::move(Src));
16630b57cec5SDimitry Andric     Operands.push_back(std::move(Dst));
16640b57cec5SDimitry Andric   }
16650b57cec5SDimitry Andric }
16660b57cec5SDimitry Andric 
VerifyAndAdjustOperands(OperandVector & OrigOperands,OperandVector & FinalOperands)16670b57cec5SDimitry Andric bool X86AsmParser::VerifyAndAdjustOperands(OperandVector &OrigOperands,
16680b57cec5SDimitry Andric                                            OperandVector &FinalOperands) {
16690b57cec5SDimitry Andric 
16700b57cec5SDimitry Andric   if (OrigOperands.size() > 1) {
16710b57cec5SDimitry Andric     // Check if sizes match, OrigOperands also contains the instruction name
16720b57cec5SDimitry Andric     assert(OrigOperands.size() == FinalOperands.size() + 1 &&
16730b57cec5SDimitry Andric            "Operand size mismatch");
16740b57cec5SDimitry Andric 
16750b57cec5SDimitry Andric     SmallVector<std::pair<SMLoc, std::string>, 2> Warnings;
16760b57cec5SDimitry Andric     // Verify types match
16770b57cec5SDimitry Andric     int RegClassID = -1;
16780b57cec5SDimitry Andric     for (unsigned int i = 0; i < FinalOperands.size(); ++i) {
16790b57cec5SDimitry Andric       X86Operand &OrigOp = static_cast<X86Operand &>(*OrigOperands[i + 1]);
16800b57cec5SDimitry Andric       X86Operand &FinalOp = static_cast<X86Operand &>(*FinalOperands[i]);
16810b57cec5SDimitry Andric 
16820b57cec5SDimitry Andric       if (FinalOp.isReg() &&
16830b57cec5SDimitry Andric           (!OrigOp.isReg() || FinalOp.getReg() != OrigOp.getReg()))
16840b57cec5SDimitry Andric         // Return false and let a normal complaint about bogus operands happen
16850b57cec5SDimitry Andric         return false;
16860b57cec5SDimitry Andric 
16870b57cec5SDimitry Andric       if (FinalOp.isMem()) {
16880b57cec5SDimitry Andric 
16890b57cec5SDimitry Andric         if (!OrigOp.isMem())
16900b57cec5SDimitry Andric           // Return false and let a normal complaint about bogus operands happen
16910b57cec5SDimitry Andric           return false;
16920b57cec5SDimitry Andric 
16930b57cec5SDimitry Andric         unsigned OrigReg = OrigOp.Mem.BaseReg;
16940b57cec5SDimitry Andric         unsigned FinalReg = FinalOp.Mem.BaseReg;
16950b57cec5SDimitry Andric 
16960b57cec5SDimitry Andric         // If we've already encounterd a register class, make sure all register
16970b57cec5SDimitry Andric         // bases are of the same register class
16980b57cec5SDimitry Andric         if (RegClassID != -1 &&
16990b57cec5SDimitry Andric             !X86MCRegisterClasses[RegClassID].contains(OrigReg)) {
17000b57cec5SDimitry Andric           return Error(OrigOp.getStartLoc(),
17010b57cec5SDimitry Andric                        "mismatching source and destination index registers");
17020b57cec5SDimitry Andric         }
17030b57cec5SDimitry Andric 
17040b57cec5SDimitry Andric         if (X86MCRegisterClasses[X86::GR64RegClassID].contains(OrigReg))
17050b57cec5SDimitry Andric           RegClassID = X86::GR64RegClassID;
17060b57cec5SDimitry Andric         else if (X86MCRegisterClasses[X86::GR32RegClassID].contains(OrigReg))
17070b57cec5SDimitry Andric           RegClassID = X86::GR32RegClassID;
17080b57cec5SDimitry Andric         else if (X86MCRegisterClasses[X86::GR16RegClassID].contains(OrigReg))
17090b57cec5SDimitry Andric           RegClassID = X86::GR16RegClassID;
17100b57cec5SDimitry Andric         else
17110b57cec5SDimitry Andric           // Unexpected register class type
17120b57cec5SDimitry Andric           // Return false and let a normal complaint about bogus operands happen
17130b57cec5SDimitry Andric           return false;
17140b57cec5SDimitry Andric 
17150b57cec5SDimitry Andric         bool IsSI = IsSIReg(FinalReg);
17160b57cec5SDimitry Andric         FinalReg = GetSIDIForRegClass(RegClassID, FinalReg, IsSI);
17170b57cec5SDimitry Andric 
17180b57cec5SDimitry Andric         if (FinalReg != OrigReg) {
17190b57cec5SDimitry Andric           std::string RegName = IsSI ? "ES:(R|E)SI" : "ES:(R|E)DI";
17200b57cec5SDimitry Andric           Warnings.push_back(std::make_pair(
17210b57cec5SDimitry Andric               OrigOp.getStartLoc(),
17220b57cec5SDimitry Andric               "memory operand is only for determining the size, " + RegName +
17230b57cec5SDimitry Andric                   " will be used for the location"));
17240b57cec5SDimitry Andric         }
17250b57cec5SDimitry Andric 
17260b57cec5SDimitry Andric         FinalOp.Mem.Size = OrigOp.Mem.Size;
17270b57cec5SDimitry Andric         FinalOp.Mem.SegReg = OrigOp.Mem.SegReg;
17280b57cec5SDimitry Andric         FinalOp.Mem.BaseReg = FinalReg;
17290b57cec5SDimitry Andric       }
17300b57cec5SDimitry Andric     }
17310b57cec5SDimitry Andric 
17320b57cec5SDimitry Andric     // Produce warnings only if all the operands passed the adjustment - prevent
17330b57cec5SDimitry Andric     // legal cases like "movsd (%rax), %xmm0" mistakenly produce warnings
17340b57cec5SDimitry Andric     for (auto &WarningMsg : Warnings) {
17350b57cec5SDimitry Andric       Warning(WarningMsg.first, WarningMsg.second);
17360b57cec5SDimitry Andric     }
17370b57cec5SDimitry Andric 
17380b57cec5SDimitry Andric     // Remove old operands
17390b57cec5SDimitry Andric     for (unsigned int i = 0; i < FinalOperands.size(); ++i)
17400b57cec5SDimitry Andric       OrigOperands.pop_back();
17410b57cec5SDimitry Andric   }
17420b57cec5SDimitry Andric   // OrigOperands.append(FinalOperands.begin(), FinalOperands.end());
1743cb14a3feSDimitry Andric   for (auto &Op : FinalOperands)
1744cb14a3feSDimitry Andric     OrigOperands.push_back(std::move(Op));
17450b57cec5SDimitry Andric 
17460b57cec5SDimitry Andric   return false;
17470b57cec5SDimitry Andric }
17480b57cec5SDimitry Andric 
parseOperand(OperandVector & Operands,StringRef Name)174981ad6265SDimitry Andric bool X86AsmParser::parseOperand(OperandVector &Operands, StringRef Name) {
17500b57cec5SDimitry Andric   if (isParsingIntelSyntax())
175181ad6265SDimitry Andric     return parseIntelOperand(Operands, Name);
1752e8d8bef9SDimitry Andric 
175381ad6265SDimitry Andric   return parseATTOperand(Operands);
17540b57cec5SDimitry Andric }
17550b57cec5SDimitry Andric 
CreateMemForMSInlineAsm(unsigned SegReg,const MCExpr * Disp,unsigned BaseReg,unsigned IndexReg,unsigned Scale,bool NonAbsMem,SMLoc Start,SMLoc End,unsigned Size,StringRef Identifier,const InlineAsmIdentifierInfo & Info,OperandVector & Operands)17565f757f3fSDimitry Andric bool X86AsmParser::CreateMemForMSInlineAsm(unsigned SegReg, const MCExpr *Disp,
17575f757f3fSDimitry Andric                                            unsigned BaseReg, unsigned IndexReg,
17585f757f3fSDimitry Andric                                            unsigned Scale, bool NonAbsMem,
17595f757f3fSDimitry Andric                                            SMLoc Start, SMLoc End,
17605f757f3fSDimitry Andric                                            unsigned Size, StringRef Identifier,
17615f757f3fSDimitry Andric                                            const InlineAsmIdentifierInfo &Info,
17625f757f3fSDimitry Andric                                            OperandVector &Operands) {
17630b57cec5SDimitry Andric   // If we found a decl other than a VarDecl, then assume it is a FuncDecl or
17640b57cec5SDimitry Andric   // some other label reference.
17650b57cec5SDimitry Andric   if (Info.isKind(InlineAsmIdentifierInfo::IK_Label)) {
17660b57cec5SDimitry Andric     // Create an absolute memory reference in order to match against
17670b57cec5SDimitry Andric     // instructions taking a PC relative operand.
1768e8d8bef9SDimitry Andric     Operands.push_back(X86Operand::CreateMem(getPointerWidth(), Disp, Start,
1769e8d8bef9SDimitry Andric                                              End, Size, Identifier,
1770e8d8bef9SDimitry Andric                                              Info.Label.Decl));
1771e8d8bef9SDimitry Andric     return false;
17720b57cec5SDimitry Andric   }
17730b57cec5SDimitry Andric   // We either have a direct symbol reference, or an offset from a symbol.  The
17740b57cec5SDimitry Andric   // parser always puts the symbol on the LHS, so look there for size
17750b57cec5SDimitry Andric   // calculation purposes.
17760b57cec5SDimitry Andric   unsigned FrontendSize = 0;
17770b57cec5SDimitry Andric   void *Decl = nullptr;
17780b57cec5SDimitry Andric   bool IsGlobalLV = false;
17790b57cec5SDimitry Andric   if (Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {
17800b57cec5SDimitry Andric     // Size is in terms of bits in this context.
17810b57cec5SDimitry Andric     FrontendSize = Info.Var.Type * 8;
17820b57cec5SDimitry Andric     Decl = Info.Var.Decl;
17830b57cec5SDimitry Andric     IsGlobalLV = Info.Var.IsGlobalLV;
17840b57cec5SDimitry Andric   }
17850b57cec5SDimitry Andric   // It is widely common for MS InlineAsm to use a global variable and one/two
17860b57cec5SDimitry Andric   // registers in a mmory expression, and though unaccessible via rip/eip.
17875f757f3fSDimitry Andric   if (IsGlobalLV) {
17885f757f3fSDimitry Andric     if (BaseReg || IndexReg) {
1789349cc55cSDimitry Andric       Operands.push_back(X86Operand::CreateMem(getPointerWidth(), Disp, Start,
179081ad6265SDimitry Andric                                                End, Size, Identifier, Decl, 0,
179181ad6265SDimitry Andric                                                BaseReg && IndexReg));
1792e8d8bef9SDimitry Andric       return false;
1793e8d8bef9SDimitry Andric     }
17945f757f3fSDimitry Andric     if (NonAbsMem)
17955f757f3fSDimitry Andric       BaseReg = 1; // Make isAbsMem() false
17965f757f3fSDimitry Andric   }
1797e8d8bef9SDimitry Andric   Operands.push_back(X86Operand::CreateMem(
1798e8d8bef9SDimitry Andric       getPointerWidth(), SegReg, Disp, BaseReg, IndexReg, Scale, Start, End,
1799e8d8bef9SDimitry Andric       Size,
1800e8d8bef9SDimitry Andric       /*DefaultBaseReg=*/X86::RIP, Identifier, Decl, FrontendSize));
1801e8d8bef9SDimitry Andric   return false;
18020b57cec5SDimitry Andric }
18030b57cec5SDimitry Andric 
18040b57cec5SDimitry Andric // Some binary bitwise operators have a named synonymous
18050b57cec5SDimitry Andric // Query a candidate string for being such a named operator
18060b57cec5SDimitry Andric // and if so - invoke the appropriate handler
ParseIntelNamedOperator(StringRef Name,IntelExprStateMachine & SM,bool & ParseError,SMLoc & End)1807480093f4SDimitry Andric bool X86AsmParser::ParseIntelNamedOperator(StringRef Name,
1808480093f4SDimitry Andric                                            IntelExprStateMachine &SM,
1809480093f4SDimitry Andric                                            bool &ParseError, SMLoc &End) {
1810e8d8bef9SDimitry Andric   // A named operator should be either lower or upper case, but not a mix...
1811e8d8bef9SDimitry Andric   // except in MASM, which uses full case-insensitivity.
18120fca6ea1SDimitry Andric   if (Name != Name.lower() && Name != Name.upper() &&
1813e8d8bef9SDimitry Andric       !getParser().isParsingMasm())
18140b57cec5SDimitry Andric     return false;
1815fe6060f1SDimitry Andric   if (Name.equals_insensitive("not")) {
18160b57cec5SDimitry Andric     SM.onNot();
1817fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("or")) {
18180b57cec5SDimitry Andric     SM.onOr();
1819fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("shl")) {
18200b57cec5SDimitry Andric     SM.onLShift();
1821fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("shr")) {
18220b57cec5SDimitry Andric     SM.onRShift();
1823fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("xor")) {
18240b57cec5SDimitry Andric     SM.onXor();
1825fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("and")) {
18260b57cec5SDimitry Andric     SM.onAnd();
1827fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("mod")) {
18280b57cec5SDimitry Andric     SM.onMod();
1829fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("offset")) {
1830480093f4SDimitry Andric     SMLoc OffsetLoc = getTok().getLoc();
1831480093f4SDimitry Andric     const MCExpr *Val = nullptr;
1832480093f4SDimitry Andric     StringRef ID;
1833480093f4SDimitry Andric     InlineAsmIdentifierInfo Info;
1834480093f4SDimitry Andric     ParseError = ParseIntelOffsetOperator(Val, ID, Info, End);
1835480093f4SDimitry Andric     if (ParseError)
1836480093f4SDimitry Andric       return true;
1837480093f4SDimitry Andric     StringRef ErrMsg;
1838480093f4SDimitry Andric     ParseError =
18395ffd83dbSDimitry Andric         SM.onOffset(Val, OffsetLoc, ID, Info, isParsingMSInlineAsm(), ErrMsg);
1840480093f4SDimitry Andric     if (ParseError)
1841480093f4SDimitry Andric       return Error(SMLoc::getFromPointer(Name.data()), ErrMsg);
1842480093f4SDimitry Andric   } else {
18430b57cec5SDimitry Andric     return false;
1844480093f4SDimitry Andric   }
1845fe6060f1SDimitry Andric   if (!Name.equals_insensitive("offset"))
1846480093f4SDimitry Andric     End = consumeToken();
18470b57cec5SDimitry Andric   return true;
18480b57cec5SDimitry Andric }
ParseMasmNamedOperator(StringRef Name,IntelExprStateMachine & SM,bool & ParseError,SMLoc & End)1849e8d8bef9SDimitry Andric bool X86AsmParser::ParseMasmNamedOperator(StringRef Name,
1850e8d8bef9SDimitry Andric                                           IntelExprStateMachine &SM,
1851e8d8bef9SDimitry Andric                                           bool &ParseError, SMLoc &End) {
1852fe6060f1SDimitry Andric   if (Name.equals_insensitive("eq")) {
1853e8d8bef9SDimitry Andric     SM.onEq();
1854fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("ne")) {
1855e8d8bef9SDimitry Andric     SM.onNE();
1856fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("lt")) {
1857e8d8bef9SDimitry Andric     SM.onLT();
1858fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("le")) {
1859e8d8bef9SDimitry Andric     SM.onLE();
1860fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("gt")) {
1861e8d8bef9SDimitry Andric     SM.onGT();
1862fe6060f1SDimitry Andric   } else if (Name.equals_insensitive("ge")) {
1863e8d8bef9SDimitry Andric     SM.onGE();
1864e8d8bef9SDimitry Andric   } else {
1865e8d8bef9SDimitry Andric     return false;
1866e8d8bef9SDimitry Andric   }
1867e8d8bef9SDimitry Andric   End = consumeToken();
1868e8d8bef9SDimitry Andric   return true;
1869e8d8bef9SDimitry Andric }
18700b57cec5SDimitry Andric 
187181ad6265SDimitry Andric // Check if current intel expression append after an operand.
187281ad6265SDimitry Andric // Like: [Operand][Intel Expression]
tryParseOperandIdx(AsmToken::TokenKind PrevTK,IntelExprStateMachine & SM)187381ad6265SDimitry Andric void X86AsmParser::tryParseOperandIdx(AsmToken::TokenKind PrevTK,
187481ad6265SDimitry Andric                                       IntelExprStateMachine &SM) {
187581ad6265SDimitry Andric   if (PrevTK != AsmToken::RBrac)
187681ad6265SDimitry Andric     return;
187781ad6265SDimitry Andric 
187881ad6265SDimitry Andric   SM.setAppendAfterOperand();
187981ad6265SDimitry Andric }
188081ad6265SDimitry Andric 
ParseIntelExpression(IntelExprStateMachine & SM,SMLoc & End)18810b57cec5SDimitry Andric bool X86AsmParser::ParseIntelExpression(IntelExprStateMachine &SM, SMLoc &End) {
18820b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
18830b57cec5SDimitry Andric   StringRef ErrMsg;
18840b57cec5SDimitry Andric 
18850b57cec5SDimitry Andric   AsmToken::TokenKind PrevTK = AsmToken::Error;
188681ad6265SDimitry Andric 
188781ad6265SDimitry Andric   if (getContext().getObjectFileInfo()->isPositionIndependent())
188881ad6265SDimitry Andric     SM.setPIC();
188981ad6265SDimitry Andric 
18900b57cec5SDimitry Andric   bool Done = false;
18910b57cec5SDimitry Andric   while (!Done) {
1892e8d8bef9SDimitry Andric     // Get a fresh reference on each loop iteration in case the previous
1893e8d8bef9SDimitry Andric     // iteration moved the token storage during UnLex().
1894e8d8bef9SDimitry Andric     const AsmToken &Tok = Parser.getTok();
1895e8d8bef9SDimitry Andric 
18960b57cec5SDimitry Andric     bool UpdateLocLex = true;
18970b57cec5SDimitry Andric     AsmToken::TokenKind TK = getLexer().getKind();
18980b57cec5SDimitry Andric 
18990b57cec5SDimitry Andric     switch (TK) {
19000b57cec5SDimitry Andric     default:
19010b57cec5SDimitry Andric       if ((Done = SM.isValidEndState()))
19020b57cec5SDimitry Andric         break;
19030b57cec5SDimitry Andric       return Error(Tok.getLoc(), "unknown token in expression");
1904e8d8bef9SDimitry Andric     case AsmToken::Error:
1905e8d8bef9SDimitry Andric       return Error(getLexer().getErrLoc(), getLexer().getErr());
1906e8d8bef9SDimitry Andric       break;
19070b57cec5SDimitry Andric     case AsmToken::Real:
19080b57cec5SDimitry Andric       // DotOperator: [ebx].0
19090b57cec5SDimitry Andric       UpdateLocLex = false;
19100b57cec5SDimitry Andric       if (ParseIntelDotOperator(SM, End))
19110b57cec5SDimitry Andric         return true;
19120b57cec5SDimitry Andric       break;
1913e8d8bef9SDimitry Andric     case AsmToken::Dot:
1914e8d8bef9SDimitry Andric       if (!Parser.isParsingMasm()) {
1915e8d8bef9SDimitry Andric         if ((Done = SM.isValidEndState()))
1916e8d8bef9SDimitry Andric           break;
1917e8d8bef9SDimitry Andric         return Error(Tok.getLoc(), "unknown token in expression");
1918e8d8bef9SDimitry Andric       }
1919e8d8bef9SDimitry Andric       // MASM allows spaces around the dot operator (e.g., "var . x")
1920e8d8bef9SDimitry Andric       Lex();
1921e8d8bef9SDimitry Andric       UpdateLocLex = false;
1922e8d8bef9SDimitry Andric       if (ParseIntelDotOperator(SM, End))
1923e8d8bef9SDimitry Andric         return true;
1924e8d8bef9SDimitry Andric       break;
1925e8d8bef9SDimitry Andric     case AsmToken::Dollar:
1926e8d8bef9SDimitry Andric       if (!Parser.isParsingMasm()) {
1927e8d8bef9SDimitry Andric         if ((Done = SM.isValidEndState()))
1928e8d8bef9SDimitry Andric           break;
1929e8d8bef9SDimitry Andric         return Error(Tok.getLoc(), "unknown token in expression");
1930e8d8bef9SDimitry Andric       }
1931bdd1243dSDimitry Andric       [[fallthrough]];
1932e8d8bef9SDimitry Andric     case AsmToken::String: {
1933e8d8bef9SDimitry Andric       if (Parser.isParsingMasm()) {
1934e8d8bef9SDimitry Andric         // MASM parsers handle strings in expressions as constants.
1935e8d8bef9SDimitry Andric         SMLoc ValueLoc = Tok.getLoc();
1936e8d8bef9SDimitry Andric         int64_t Res;
1937e8d8bef9SDimitry Andric         const MCExpr *Val;
1938e8d8bef9SDimitry Andric         if (Parser.parsePrimaryExpr(Val, End, nullptr))
1939e8d8bef9SDimitry Andric           return true;
1940e8d8bef9SDimitry Andric         UpdateLocLex = false;
1941e8d8bef9SDimitry Andric         if (!Val->evaluateAsAbsolute(Res, getStreamer().getAssemblerPtr()))
1942e8d8bef9SDimitry Andric           return Error(ValueLoc, "expected absolute value");
1943e8d8bef9SDimitry Andric         if (SM.onInteger(Res, ErrMsg))
1944e8d8bef9SDimitry Andric           return Error(ValueLoc, ErrMsg);
1945e8d8bef9SDimitry Andric         break;
1946e8d8bef9SDimitry Andric       }
1947bdd1243dSDimitry Andric       [[fallthrough]];
1948e8d8bef9SDimitry Andric     }
19490b57cec5SDimitry Andric     case AsmToken::At:
19500b57cec5SDimitry Andric     case AsmToken::Identifier: {
19510b57cec5SDimitry Andric       SMLoc IdentLoc = Tok.getLoc();
19520b57cec5SDimitry Andric       StringRef Identifier = Tok.getString();
19530b57cec5SDimitry Andric       UpdateLocLex = false;
1954e8d8bef9SDimitry Andric       if (Parser.isParsingMasm()) {
1955e8d8bef9SDimitry Andric         size_t DotOffset = Identifier.find_first_of('.');
1956e8d8bef9SDimitry Andric         if (DotOffset != StringRef::npos) {
1957e8d8bef9SDimitry Andric           consumeToken();
1958e8d8bef9SDimitry Andric           StringRef LHS = Identifier.slice(0, DotOffset);
1959e8d8bef9SDimitry Andric           StringRef Dot = Identifier.slice(DotOffset, DotOffset + 1);
1960e8d8bef9SDimitry Andric           StringRef RHS = Identifier.slice(DotOffset + 1, StringRef::npos);
1961e8d8bef9SDimitry Andric           if (!RHS.empty()) {
1962e8d8bef9SDimitry Andric             getLexer().UnLex(AsmToken(AsmToken::Identifier, RHS));
1963e8d8bef9SDimitry Andric           }
1964e8d8bef9SDimitry Andric           getLexer().UnLex(AsmToken(AsmToken::Dot, Dot));
1965e8d8bef9SDimitry Andric           if (!LHS.empty()) {
1966e8d8bef9SDimitry Andric             getLexer().UnLex(AsmToken(AsmToken::Identifier, LHS));
1967e8d8bef9SDimitry Andric           }
1968e8d8bef9SDimitry Andric           break;
1969e8d8bef9SDimitry Andric         }
1970e8d8bef9SDimitry Andric       }
19715ffd83dbSDimitry Andric       // (MASM only) <TYPE> PTR operator
19725ffd83dbSDimitry Andric       if (Parser.isParsingMasm()) {
19735ffd83dbSDimitry Andric         const AsmToken &NextTok = getLexer().peekTok();
19745ffd83dbSDimitry Andric         if (NextTok.is(AsmToken::Identifier) &&
1975fe6060f1SDimitry Andric             NextTok.getIdentifier().equals_insensitive("ptr")) {
1976e8d8bef9SDimitry Andric           AsmTypeInfo Info;
1977e8d8bef9SDimitry Andric           if (Parser.lookUpType(Identifier, Info))
1978e8d8bef9SDimitry Andric             return Error(Tok.getLoc(), "unknown type");
1979e8d8bef9SDimitry Andric           SM.onCast(Info);
19805ffd83dbSDimitry Andric           // Eat type and PTR.
19815ffd83dbSDimitry Andric           consumeToken();
19825ffd83dbSDimitry Andric           End = consumeToken();
19830b57cec5SDimitry Andric           break;
19840b57cec5SDimitry Andric         }
19855ffd83dbSDimitry Andric       }
19865ffd83dbSDimitry Andric       // Register, or (MASM only) <register>.<field>
1987bdd1243dSDimitry Andric       MCRegister Reg;
19885ffd83dbSDimitry Andric       if (Tok.is(AsmToken::Identifier)) {
19895ffd83dbSDimitry Andric         if (!ParseRegister(Reg, IdentLoc, End, /*RestoreOnFailure=*/true)) {
19905ffd83dbSDimitry Andric           if (SM.onRegister(Reg, ErrMsg))
19915ffd83dbSDimitry Andric             return Error(IdentLoc, ErrMsg);
19925ffd83dbSDimitry Andric           break;
19935ffd83dbSDimitry Andric         }
19945ffd83dbSDimitry Andric         if (Parser.isParsingMasm()) {
19955ffd83dbSDimitry Andric           const std::pair<StringRef, StringRef> IDField =
19965ffd83dbSDimitry Andric               Tok.getString().split('.');
19975ffd83dbSDimitry Andric           const StringRef ID = IDField.first, Field = IDField.second;
19985ffd83dbSDimitry Andric           SMLoc IDEndLoc = SMLoc::getFromPointer(ID.data() + ID.size());
19995ffd83dbSDimitry Andric           if (!Field.empty() &&
20005ffd83dbSDimitry Andric               !MatchRegisterByName(Reg, ID, IdentLoc, IDEndLoc)) {
20015ffd83dbSDimitry Andric             if (SM.onRegister(Reg, ErrMsg))
20025ffd83dbSDimitry Andric               return Error(IdentLoc, ErrMsg);
20035ffd83dbSDimitry Andric 
2004e8d8bef9SDimitry Andric             AsmFieldInfo Info;
20055ffd83dbSDimitry Andric             SMLoc FieldStartLoc = SMLoc::getFromPointer(Field.data());
2006e8d8bef9SDimitry Andric             if (Parser.lookUpField(Field, Info))
20075ffd83dbSDimitry Andric               return Error(FieldStartLoc, "unknown offset");
20085ffd83dbSDimitry Andric             else if (SM.onPlus(ErrMsg))
20095ffd83dbSDimitry Andric               return Error(getTok().getLoc(), ErrMsg);
2010e8d8bef9SDimitry Andric             else if (SM.onInteger(Info.Offset, ErrMsg))
20115ffd83dbSDimitry Andric               return Error(IdentLoc, ErrMsg);
2012e8d8bef9SDimitry Andric             SM.setTypeInfo(Info.Type);
20135ffd83dbSDimitry Andric 
20145ffd83dbSDimitry Andric             End = consumeToken();
20155ffd83dbSDimitry Andric             break;
20165ffd83dbSDimitry Andric           }
20175ffd83dbSDimitry Andric         }
20185ffd83dbSDimitry Andric       }
20190b57cec5SDimitry Andric       // Operator synonymous ("not", "or" etc.)
2020480093f4SDimitry Andric       bool ParseError = false;
2021480093f4SDimitry Andric       if (ParseIntelNamedOperator(Identifier, SM, ParseError, End)) {
2022480093f4SDimitry Andric         if (ParseError)
2023480093f4SDimitry Andric           return true;
20240b57cec5SDimitry Andric         break;
2025480093f4SDimitry Andric       }
2026e8d8bef9SDimitry Andric       if (Parser.isParsingMasm() &&
2027e8d8bef9SDimitry Andric           ParseMasmNamedOperator(Identifier, SM, ParseError, End)) {
2028e8d8bef9SDimitry Andric         if (ParseError)
2029e8d8bef9SDimitry Andric           return true;
2030e8d8bef9SDimitry Andric         break;
2031e8d8bef9SDimitry Andric       }
20320b57cec5SDimitry Andric       // Symbol reference, when parsing assembly content
20330b57cec5SDimitry Andric       InlineAsmIdentifierInfo Info;
2034e8d8bef9SDimitry Andric       AsmFieldInfo FieldInfo;
20350b57cec5SDimitry Andric       const MCExpr *Val;
20365ffd83dbSDimitry Andric       if (isParsingMSInlineAsm() || Parser.isParsingMasm()) {
20375ffd83dbSDimitry Andric         // MS Dot Operator expression
20385ffd83dbSDimitry Andric         if (Identifier.count('.') &&
20395ffd83dbSDimitry Andric             (PrevTK == AsmToken::RBrac || PrevTK == AsmToken::RParen)) {
20405ffd83dbSDimitry Andric           if (ParseIntelDotOperator(SM, End))
20415ffd83dbSDimitry Andric             return true;
20420b57cec5SDimitry Andric           break;
20430b57cec5SDimitry Andric         }
20445ffd83dbSDimitry Andric       }
20455ffd83dbSDimitry Andric       if (isParsingMSInlineAsm()) {
20460b57cec5SDimitry Andric         // MS InlineAsm operators (TYPE/LENGTH/SIZE)
20470b57cec5SDimitry Andric         if (unsigned OpKind = IdentifyIntelInlineAsmOperator(Identifier)) {
20480b57cec5SDimitry Andric           if (int64_t Val = ParseIntelInlineAsmOperator(OpKind)) {
20490b57cec5SDimitry Andric             if (SM.onInteger(Val, ErrMsg))
20500b57cec5SDimitry Andric               return Error(IdentLoc, ErrMsg);
2051e8d8bef9SDimitry Andric           } else {
20520b57cec5SDimitry Andric             return true;
2053e8d8bef9SDimitry Andric           }
20540b57cec5SDimitry Andric           break;
20550b57cec5SDimitry Andric         }
20560b57cec5SDimitry Andric         // MS InlineAsm identifier
20570b57cec5SDimitry Andric         // Call parseIdentifier() to combine @ with the identifier behind it.
20580b57cec5SDimitry Andric         if (TK == AsmToken::At && Parser.parseIdentifier(Identifier))
20590b57cec5SDimitry Andric           return Error(IdentLoc, "expected identifier");
20600b57cec5SDimitry Andric         if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info, false, End))
20610b57cec5SDimitry Andric           return true;
2062e8d8bef9SDimitry Andric         else if (SM.onIdentifierExpr(Val, Identifier, Info, FieldInfo.Type,
2063e8d8bef9SDimitry Andric                                      true, ErrMsg))
20640b57cec5SDimitry Andric           return Error(IdentLoc, ErrMsg);
20650b57cec5SDimitry Andric         break;
20660b57cec5SDimitry Andric       }
2067e8d8bef9SDimitry Andric       if (Parser.isParsingMasm()) {
2068e8d8bef9SDimitry Andric         if (unsigned OpKind = IdentifyMasmOperator(Identifier)) {
2069e8d8bef9SDimitry Andric           int64_t Val;
2070e8d8bef9SDimitry Andric           if (ParseMasmOperator(OpKind, Val))
2071e8d8bef9SDimitry Andric             return true;
2072e8d8bef9SDimitry Andric           if (SM.onInteger(Val, ErrMsg))
2073e8d8bef9SDimitry Andric             return Error(IdentLoc, ErrMsg);
2074e8d8bef9SDimitry Andric           break;
2075e8d8bef9SDimitry Andric         }
2076e8d8bef9SDimitry Andric         if (!getParser().lookUpType(Identifier, FieldInfo.Type)) {
2077e8d8bef9SDimitry Andric           // Field offset immediate; <TYPE>.<field specification>
2078e8d8bef9SDimitry Andric           Lex(); // eat type
2079e8d8bef9SDimitry Andric           bool EndDot = parseOptionalToken(AsmToken::Dot);
2080e8d8bef9SDimitry Andric           while (EndDot || (getTok().is(AsmToken::Identifier) &&
20815f757f3fSDimitry Andric                             getTok().getString().starts_with("."))) {
2082e8d8bef9SDimitry Andric             getParser().parseIdentifier(Identifier);
2083e8d8bef9SDimitry Andric             if (!EndDot)
2084e8d8bef9SDimitry Andric               Identifier.consume_front(".");
2085e8d8bef9SDimitry Andric             EndDot = Identifier.consume_back(".");
2086e8d8bef9SDimitry Andric             if (getParser().lookUpField(FieldInfo.Type.Name, Identifier,
2087e8d8bef9SDimitry Andric                                         FieldInfo)) {
2088e8d8bef9SDimitry Andric               SMLoc IDEnd =
2089e8d8bef9SDimitry Andric                   SMLoc::getFromPointer(Identifier.data() + Identifier.size());
2090e8d8bef9SDimitry Andric               return Error(IdentLoc, "Unable to lookup field reference!",
2091e8d8bef9SDimitry Andric                            SMRange(IdentLoc, IDEnd));
2092e8d8bef9SDimitry Andric             }
2093e8d8bef9SDimitry Andric             if (!EndDot)
2094e8d8bef9SDimitry Andric               EndDot = parseOptionalToken(AsmToken::Dot);
2095e8d8bef9SDimitry Andric           }
2096e8d8bef9SDimitry Andric           if (SM.onInteger(FieldInfo.Offset, ErrMsg))
2097e8d8bef9SDimitry Andric             return Error(IdentLoc, ErrMsg);
2098e8d8bef9SDimitry Andric           break;
2099e8d8bef9SDimitry Andric         }
2100e8d8bef9SDimitry Andric       }
2101e8d8bef9SDimitry Andric       if (getParser().parsePrimaryExpr(Val, End, &FieldInfo.Type)) {
21025ffd83dbSDimitry Andric         return Error(Tok.getLoc(), "Unexpected identifier!");
2103e8d8bef9SDimitry Andric       } else if (SM.onIdentifierExpr(Val, Identifier, Info, FieldInfo.Type,
2104e8d8bef9SDimitry Andric                                      false, ErrMsg)) {
21055ffd83dbSDimitry Andric         return Error(IdentLoc, ErrMsg);
21065ffd83dbSDimitry Andric       }
21075ffd83dbSDimitry Andric       break;
21085ffd83dbSDimitry Andric     }
21090b57cec5SDimitry Andric     case AsmToken::Integer: {
21100b57cec5SDimitry Andric       // Look for 'b' or 'f' following an Integer as a directional label
21110b57cec5SDimitry Andric       SMLoc Loc = getTok().getLoc();
21120b57cec5SDimitry Andric       int64_t IntVal = getTok().getIntVal();
21130b57cec5SDimitry Andric       End = consumeToken();
21140b57cec5SDimitry Andric       UpdateLocLex = false;
21150b57cec5SDimitry Andric       if (getLexer().getKind() == AsmToken::Identifier) {
21160b57cec5SDimitry Andric         StringRef IDVal = getTok().getString();
21170b57cec5SDimitry Andric         if (IDVal == "f" || IDVal == "b") {
21180b57cec5SDimitry Andric           MCSymbol *Sym =
21190b57cec5SDimitry Andric               getContext().getDirectionalLocalSymbol(IntVal, IDVal == "b");
21200b57cec5SDimitry Andric           MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
21210b57cec5SDimitry Andric           const MCExpr *Val =
21220b57cec5SDimitry Andric               MCSymbolRefExpr::create(Sym, Variant, getContext());
21230b57cec5SDimitry Andric           if (IDVal == "b" && Sym->isUndefined())
21240b57cec5SDimitry Andric             return Error(Loc, "invalid reference to undefined symbol");
21250b57cec5SDimitry Andric           StringRef Identifier = Sym->getName();
21260b57cec5SDimitry Andric           InlineAsmIdentifierInfo Info;
2127e8d8bef9SDimitry Andric           AsmTypeInfo Type;
2128e8d8bef9SDimitry Andric           if (SM.onIdentifierExpr(Val, Identifier, Info, Type,
2129e8d8bef9SDimitry Andric                                   isParsingMSInlineAsm(), ErrMsg))
21300b57cec5SDimitry Andric             return Error(Loc, ErrMsg);
21310b57cec5SDimitry Andric           End = consumeToken();
21320b57cec5SDimitry Andric         } else {
21330b57cec5SDimitry Andric           if (SM.onInteger(IntVal, ErrMsg))
21340b57cec5SDimitry Andric             return Error(Loc, ErrMsg);
21350b57cec5SDimitry Andric         }
21360b57cec5SDimitry Andric       } else {
21370b57cec5SDimitry Andric         if (SM.onInteger(IntVal, ErrMsg))
21380b57cec5SDimitry Andric           return Error(Loc, ErrMsg);
21390b57cec5SDimitry Andric       }
21400b57cec5SDimitry Andric       break;
21410b57cec5SDimitry Andric     }
21420b57cec5SDimitry Andric     case AsmToken::Plus:
21430b57cec5SDimitry Andric       if (SM.onPlus(ErrMsg))
21440b57cec5SDimitry Andric         return Error(getTok().getLoc(), ErrMsg);
21450b57cec5SDimitry Andric       break;
21460b57cec5SDimitry Andric     case AsmToken::Minus:
21470b57cec5SDimitry Andric       if (SM.onMinus(ErrMsg))
21480b57cec5SDimitry Andric         return Error(getTok().getLoc(), ErrMsg);
21490b57cec5SDimitry Andric       break;
21500b57cec5SDimitry Andric     case AsmToken::Tilde:   SM.onNot(); break;
21510b57cec5SDimitry Andric     case AsmToken::Star:    SM.onStar(); break;
21520b57cec5SDimitry Andric     case AsmToken::Slash:   SM.onDivide(); break;
21530b57cec5SDimitry Andric     case AsmToken::Percent: SM.onMod(); break;
21540b57cec5SDimitry Andric     case AsmToken::Pipe:    SM.onOr(); break;
21550b57cec5SDimitry Andric     case AsmToken::Caret:   SM.onXor(); break;
21560b57cec5SDimitry Andric     case AsmToken::Amp:     SM.onAnd(); break;
21570b57cec5SDimitry Andric     case AsmToken::LessLess:
21580b57cec5SDimitry Andric                             SM.onLShift(); break;
21590b57cec5SDimitry Andric     case AsmToken::GreaterGreater:
21600b57cec5SDimitry Andric                             SM.onRShift(); break;
21610b57cec5SDimitry Andric     case AsmToken::LBrac:
21620b57cec5SDimitry Andric       if (SM.onLBrac())
21630b57cec5SDimitry Andric         return Error(Tok.getLoc(), "unexpected bracket encountered");
216481ad6265SDimitry Andric       tryParseOperandIdx(PrevTK, SM);
21650b57cec5SDimitry Andric       break;
21660b57cec5SDimitry Andric     case AsmToken::RBrac:
216781ad6265SDimitry Andric       if (SM.onRBrac(ErrMsg)) {
216881ad6265SDimitry Andric         return Error(Tok.getLoc(), ErrMsg);
216981ad6265SDimitry Andric       }
21700b57cec5SDimitry Andric       break;
21710b57cec5SDimitry Andric     case AsmToken::LParen:  SM.onLParen(); break;
21720b57cec5SDimitry Andric     case AsmToken::RParen:  SM.onRParen(); break;
21730b57cec5SDimitry Andric     }
21740b57cec5SDimitry Andric     if (SM.hadError())
21750b57cec5SDimitry Andric       return Error(Tok.getLoc(), "unknown token in expression");
21760b57cec5SDimitry Andric 
21770b57cec5SDimitry Andric     if (!Done && UpdateLocLex)
21780b57cec5SDimitry Andric       End = consumeToken();
21790b57cec5SDimitry Andric 
21800b57cec5SDimitry Andric     PrevTK = TK;
21810b57cec5SDimitry Andric   }
21820b57cec5SDimitry Andric   return false;
21830b57cec5SDimitry Andric }
21840b57cec5SDimitry Andric 
RewriteIntelExpression(IntelExprStateMachine & SM,SMLoc Start,SMLoc End)21850b57cec5SDimitry Andric void X86AsmParser::RewriteIntelExpression(IntelExprStateMachine &SM,
21860b57cec5SDimitry Andric                                           SMLoc Start, SMLoc End) {
21870b57cec5SDimitry Andric   SMLoc Loc = Start;
21880b57cec5SDimitry Andric   unsigned ExprLen = End.getPointer() - Start.getPointer();
21890b57cec5SDimitry Andric   // Skip everything before a symbol displacement (if we have one)
2190480093f4SDimitry Andric   if (SM.getSym() && !SM.isOffsetOperator()) {
21910b57cec5SDimitry Andric     StringRef SymName = SM.getSymName();
21920b57cec5SDimitry Andric     if (unsigned Len = SymName.data() - Start.getPointer())
21930b57cec5SDimitry Andric       InstInfo->AsmRewrites->emplace_back(AOK_Skip, Start, Len);
21940b57cec5SDimitry Andric     Loc = SMLoc::getFromPointer(SymName.data() + SymName.size());
21950b57cec5SDimitry Andric     ExprLen = End.getPointer() - (SymName.data() + SymName.size());
21960b57cec5SDimitry Andric     // If we have only a symbol than there's no need for complex rewrite,
21970b57cec5SDimitry Andric     // simply skip everything after it
21980b57cec5SDimitry Andric     if (!(SM.getBaseReg() || SM.getIndexReg() || SM.getImm())) {
21990b57cec5SDimitry Andric       if (ExprLen)
22000b57cec5SDimitry Andric         InstInfo->AsmRewrites->emplace_back(AOK_Skip, Loc, ExprLen);
22010b57cec5SDimitry Andric       return;
22020b57cec5SDimitry Andric     }
22030b57cec5SDimitry Andric   }
22040b57cec5SDimitry Andric   // Build an Intel Expression rewrite
22050b57cec5SDimitry Andric   StringRef BaseRegStr;
22060b57cec5SDimitry Andric   StringRef IndexRegStr;
2207480093f4SDimitry Andric   StringRef OffsetNameStr;
22080b57cec5SDimitry Andric   if (SM.getBaseReg())
22090b57cec5SDimitry Andric     BaseRegStr = X86IntelInstPrinter::getRegisterName(SM.getBaseReg());
22100b57cec5SDimitry Andric   if (SM.getIndexReg())
22110b57cec5SDimitry Andric     IndexRegStr = X86IntelInstPrinter::getRegisterName(SM.getIndexReg());
2212480093f4SDimitry Andric   if (SM.isOffsetOperator())
2213480093f4SDimitry Andric     OffsetNameStr = SM.getSymName();
22140b57cec5SDimitry Andric   // Emit it
2215480093f4SDimitry Andric   IntelExpr Expr(BaseRegStr, IndexRegStr, SM.getScale(), OffsetNameStr,
2216480093f4SDimitry Andric                  SM.getImm(), SM.isMemExpr());
22170b57cec5SDimitry Andric   InstInfo->AsmRewrites->emplace_back(Loc, ExprLen, Expr);
22180b57cec5SDimitry Andric }
22190b57cec5SDimitry Andric 
22200b57cec5SDimitry Andric // Inline assembly may use variable names with namespace alias qualifiers.
ParseIntelInlineAsmIdentifier(const MCExpr * & Val,StringRef & Identifier,InlineAsmIdentifierInfo & Info,bool IsUnevaluatedOperand,SMLoc & End,bool IsParsingOffsetOperator)2221480093f4SDimitry Andric bool X86AsmParser::ParseIntelInlineAsmIdentifier(
2222480093f4SDimitry Andric     const MCExpr *&Val, StringRef &Identifier, InlineAsmIdentifierInfo &Info,
2223480093f4SDimitry Andric     bool IsUnevaluatedOperand, SMLoc &End, bool IsParsingOffsetOperator) {
22240b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
22255ffd83dbSDimitry Andric   assert(isParsingMSInlineAsm() && "Expected to be parsing inline assembly.");
22260b57cec5SDimitry Andric   Val = nullptr;
22270b57cec5SDimitry Andric 
22280b57cec5SDimitry Andric   StringRef LineBuf(Identifier.data());
22290b57cec5SDimitry Andric   SemaCallback->LookupInlineAsmIdentifier(LineBuf, Info, IsUnevaluatedOperand);
22300b57cec5SDimitry Andric 
22310b57cec5SDimitry Andric   const AsmToken &Tok = Parser.getTok();
22320b57cec5SDimitry Andric   SMLoc Loc = Tok.getLoc();
22330b57cec5SDimitry Andric 
22340b57cec5SDimitry Andric   // Advance the token stream until the end of the current token is
22350b57cec5SDimitry Andric   // after the end of what the frontend claimed.
22360b57cec5SDimitry Andric   const char *EndPtr = Tok.getLoc().getPointer() + LineBuf.size();
22370b57cec5SDimitry Andric   do {
22380b57cec5SDimitry Andric     End = Tok.getEndLoc();
22390b57cec5SDimitry Andric     getLexer().Lex();
22400b57cec5SDimitry Andric   } while (End.getPointer() < EndPtr);
22410b57cec5SDimitry Andric   Identifier = LineBuf;
22420b57cec5SDimitry Andric 
22430b57cec5SDimitry Andric   // The frontend should end parsing on an assembler token boundary, unless it
22440b57cec5SDimitry Andric   // failed parsing.
22450b57cec5SDimitry Andric   assert((End.getPointer() == EndPtr ||
22460b57cec5SDimitry Andric           Info.isKind(InlineAsmIdentifierInfo::IK_Invalid)) &&
22470b57cec5SDimitry Andric           "frontend claimed part of a token?");
22480b57cec5SDimitry Andric 
22490b57cec5SDimitry Andric   // If the identifier lookup was unsuccessful, assume that we are dealing with
22500b57cec5SDimitry Andric   // a label.
22510b57cec5SDimitry Andric   if (Info.isKind(InlineAsmIdentifierInfo::IK_Invalid)) {
22520b57cec5SDimitry Andric     StringRef InternalName =
22530b57cec5SDimitry Andric       SemaCallback->LookupInlineAsmLabel(Identifier, getSourceManager(),
22540b57cec5SDimitry Andric                                          Loc, false);
22550b57cec5SDimitry Andric     assert(InternalName.size() && "We should have an internal name here.");
2256480093f4SDimitry Andric     // Push a rewrite for replacing the identifier name with the internal name,
2257480093f4SDimitry Andric     // unless we are parsing the operand of an offset operator
2258480093f4SDimitry Andric     if (!IsParsingOffsetOperator)
22590b57cec5SDimitry Andric       InstInfo->AsmRewrites->emplace_back(AOK_Label, Loc, Identifier.size(),
22600b57cec5SDimitry Andric                                           InternalName);
2261480093f4SDimitry Andric     else
2262480093f4SDimitry Andric       Identifier = InternalName;
22630b57cec5SDimitry Andric   } else if (Info.isKind(InlineAsmIdentifierInfo::IK_EnumVal))
22640b57cec5SDimitry Andric     return false;
22650b57cec5SDimitry Andric   // Create the symbol reference.
22660b57cec5SDimitry Andric   MCSymbol *Sym = getContext().getOrCreateSymbol(Identifier);
22670b57cec5SDimitry Andric   MCSymbolRefExpr::VariantKind Variant = MCSymbolRefExpr::VK_None;
22680b57cec5SDimitry Andric   Val = MCSymbolRefExpr::create(Sym, Variant, getParser().getContext());
22690b57cec5SDimitry Andric   return false;
22700b57cec5SDimitry Andric }
22710b57cec5SDimitry Andric 
22720b57cec5SDimitry Andric //ParseRoundingModeOp - Parse AVX-512 rounding mode operand
ParseRoundingModeOp(SMLoc Start,OperandVector & Operands)2273e8d8bef9SDimitry Andric bool X86AsmParser::ParseRoundingModeOp(SMLoc Start, OperandVector &Operands) {
22740b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
22750b57cec5SDimitry Andric   const AsmToken &Tok = Parser.getTok();
22760b57cec5SDimitry Andric   // Eat "{" and mark the current place.
22770b57cec5SDimitry Andric   const SMLoc consumedToken = consumeToken();
22780b57cec5SDimitry Andric   if (Tok.isNot(AsmToken::Identifier))
2279e8d8bef9SDimitry Andric     return Error(Tok.getLoc(), "Expected an identifier after {");
22805f757f3fSDimitry Andric   if (Tok.getIdentifier().starts_with("r")) {
22810b57cec5SDimitry Andric     int rndMode = StringSwitch<int>(Tok.getIdentifier())
22820b57cec5SDimitry Andric       .Case("rn", X86::STATIC_ROUNDING::TO_NEAREST_INT)
22830b57cec5SDimitry Andric       .Case("rd", X86::STATIC_ROUNDING::TO_NEG_INF)
22840b57cec5SDimitry Andric       .Case("ru", X86::STATIC_ROUNDING::TO_POS_INF)
22850b57cec5SDimitry Andric       .Case("rz", X86::STATIC_ROUNDING::TO_ZERO)
22860b57cec5SDimitry Andric       .Default(-1);
22870b57cec5SDimitry Andric     if (-1 == rndMode)
2288e8d8bef9SDimitry Andric       return Error(Tok.getLoc(), "Invalid rounding mode.");
22890b57cec5SDimitry Andric      Parser.Lex();  // Eat "r*" of r*-sae
22900b57cec5SDimitry Andric     if (!getLexer().is(AsmToken::Minus))
2291e8d8bef9SDimitry Andric       return Error(Tok.getLoc(), "Expected - at this point");
22920b57cec5SDimitry Andric     Parser.Lex();  // Eat "-"
22930b57cec5SDimitry Andric     Parser.Lex();  // Eat the sae
22940b57cec5SDimitry Andric     if (!getLexer().is(AsmToken::RCurly))
2295e8d8bef9SDimitry Andric       return Error(Tok.getLoc(), "Expected } at this point");
22960b57cec5SDimitry Andric     SMLoc End = Tok.getEndLoc();
22970b57cec5SDimitry Andric     Parser.Lex();  // Eat "}"
22980b57cec5SDimitry Andric     const MCExpr *RndModeOp =
22990b57cec5SDimitry Andric       MCConstantExpr::create(rndMode, Parser.getContext());
2300e8d8bef9SDimitry Andric     Operands.push_back(X86Operand::CreateImm(RndModeOp, Start, End));
2301e8d8bef9SDimitry Andric     return false;
23020b57cec5SDimitry Andric   }
23030fca6ea1SDimitry Andric   if (Tok.getIdentifier() == "sae") {
23040b57cec5SDimitry Andric     Parser.Lex();  // Eat the sae
23050b57cec5SDimitry Andric     if (!getLexer().is(AsmToken::RCurly))
2306e8d8bef9SDimitry Andric       return Error(Tok.getLoc(), "Expected } at this point");
23070b57cec5SDimitry Andric     Parser.Lex();  // Eat "}"
2308e8d8bef9SDimitry Andric     Operands.push_back(X86Operand::CreateToken("{sae}", consumedToken));
2309e8d8bef9SDimitry Andric     return false;
23100b57cec5SDimitry Andric   }
2311e8d8bef9SDimitry Andric   return Error(Tok.getLoc(), "unknown token in expression");
23120b57cec5SDimitry Andric }
23130b57cec5SDimitry Andric 
23140fca6ea1SDimitry Andric /// Parse condtional flags for CCMP/CTEST, e.g {dfv=of,sf,zf,cf} right after
23150fca6ea1SDimitry Andric /// mnemonic.
parseCFlagsOp(OperandVector & Operands)23160fca6ea1SDimitry Andric bool X86AsmParser::parseCFlagsOp(OperandVector &Operands) {
23170fca6ea1SDimitry Andric   MCAsmParser &Parser = getParser();
23180fca6ea1SDimitry Andric   AsmToken Tok = Parser.getTok();
23190fca6ea1SDimitry Andric   const SMLoc Start = Tok.getLoc();
23200fca6ea1SDimitry Andric   if (!Tok.is(AsmToken::LCurly))
23210fca6ea1SDimitry Andric     return Error(Tok.getLoc(), "Expected { at this point");
23220fca6ea1SDimitry Andric   Parser.Lex(); // Eat "{"
23230fca6ea1SDimitry Andric   Tok = Parser.getTok();
23240fca6ea1SDimitry Andric   if (Tok.getIdentifier().lower() != "dfv")
23250fca6ea1SDimitry Andric     return Error(Tok.getLoc(), "Expected dfv at this point");
23260fca6ea1SDimitry Andric   Parser.Lex(); // Eat "dfv"
23270fca6ea1SDimitry Andric   Tok = Parser.getTok();
23280fca6ea1SDimitry Andric   if (!Tok.is(AsmToken::Equal))
23290fca6ea1SDimitry Andric     return Error(Tok.getLoc(), "Expected = at this point");
23300fca6ea1SDimitry Andric   Parser.Lex(); // Eat "="
23310fca6ea1SDimitry Andric 
23320fca6ea1SDimitry Andric   Tok = Parser.getTok();
23330fca6ea1SDimitry Andric   SMLoc End;
23340fca6ea1SDimitry Andric   if (Tok.is(AsmToken::RCurly)) {
23350fca6ea1SDimitry Andric     End = Tok.getEndLoc();
23360fca6ea1SDimitry Andric     Operands.push_back(X86Operand::CreateImm(
23370fca6ea1SDimitry Andric         MCConstantExpr::create(0, Parser.getContext()), Start, End));
23380fca6ea1SDimitry Andric     Parser.Lex(); // Eat "}"
23390fca6ea1SDimitry Andric     return false;
23400fca6ea1SDimitry Andric   }
23410fca6ea1SDimitry Andric   unsigned CFlags = 0;
23420fca6ea1SDimitry Andric   for (unsigned I = 0; I < 4; ++I) {
23430fca6ea1SDimitry Andric     Tok = Parser.getTok();
23440fca6ea1SDimitry Andric     unsigned CFlag = StringSwitch<unsigned>(Tok.getIdentifier().lower())
23450fca6ea1SDimitry Andric                          .Case("of", 0x8)
23460fca6ea1SDimitry Andric                          .Case("sf", 0x4)
23470fca6ea1SDimitry Andric                          .Case("zf", 0x2)
23480fca6ea1SDimitry Andric                          .Case("cf", 0x1)
23490fca6ea1SDimitry Andric                          .Default(~0U);
23500fca6ea1SDimitry Andric     if (CFlag == ~0U)
23510fca6ea1SDimitry Andric       return Error(Tok.getLoc(), "Invalid conditional flags");
23520fca6ea1SDimitry Andric 
23530fca6ea1SDimitry Andric     if (CFlags & CFlag)
23540fca6ea1SDimitry Andric       return Error(Tok.getLoc(), "Duplicated conditional flag");
23550fca6ea1SDimitry Andric     CFlags |= CFlag;
23560fca6ea1SDimitry Andric 
23570fca6ea1SDimitry Andric     Parser.Lex(); // Eat one conditional flag
23580fca6ea1SDimitry Andric     Tok = Parser.getTok();
23590fca6ea1SDimitry Andric     if (Tok.is(AsmToken::RCurly)) {
23600fca6ea1SDimitry Andric       End = Tok.getEndLoc();
23610fca6ea1SDimitry Andric       Operands.push_back(X86Operand::CreateImm(
23620fca6ea1SDimitry Andric           MCConstantExpr::create(CFlags, Parser.getContext()), Start, End));
23630fca6ea1SDimitry Andric       Parser.Lex(); // Eat "}"
23640fca6ea1SDimitry Andric       return false;
23650fca6ea1SDimitry Andric     } else if (I == 3) {
23660fca6ea1SDimitry Andric       return Error(Tok.getLoc(), "Expected } at this point");
23670fca6ea1SDimitry Andric     } else if (Tok.isNot(AsmToken::Comma)) {
23680fca6ea1SDimitry Andric       return Error(Tok.getLoc(), "Expected } or , at this point");
23690fca6ea1SDimitry Andric     }
23700fca6ea1SDimitry Andric     Parser.Lex(); // Eat ","
23710fca6ea1SDimitry Andric   }
23720fca6ea1SDimitry Andric   llvm_unreachable("Unexpected control flow");
23730fca6ea1SDimitry Andric }
23740fca6ea1SDimitry Andric 
23750b57cec5SDimitry Andric /// Parse the '.' operator.
ParseIntelDotOperator(IntelExprStateMachine & SM,SMLoc & End)23765ffd83dbSDimitry Andric bool X86AsmParser::ParseIntelDotOperator(IntelExprStateMachine &SM,
23775ffd83dbSDimitry Andric                                          SMLoc &End) {
23780b57cec5SDimitry Andric   const AsmToken &Tok = getTok();
2379e8d8bef9SDimitry Andric   AsmFieldInfo Info;
23800b57cec5SDimitry Andric 
23810b57cec5SDimitry Andric   // Drop the optional '.'.
23820b57cec5SDimitry Andric   StringRef DotDispStr = Tok.getString();
2383647cbc5dSDimitry Andric   DotDispStr.consume_front(".");
2384e8d8bef9SDimitry Andric   StringRef TrailingDot;
23850b57cec5SDimitry Andric 
23860b57cec5SDimitry Andric   // .Imm gets lexed as a real.
23870b57cec5SDimitry Andric   if (Tok.is(AsmToken::Real)) {
23880b57cec5SDimitry Andric     APInt DotDisp;
238906c3fb27SDimitry Andric     if (DotDispStr.getAsInteger(10, DotDisp))
239006c3fb27SDimitry Andric       return Error(Tok.getLoc(), "Unexpected offset");
2391e8d8bef9SDimitry Andric     Info.Offset = DotDisp.getZExtValue();
23925ffd83dbSDimitry Andric   } else if ((isParsingMSInlineAsm() || getParser().isParsingMasm()) &&
23935ffd83dbSDimitry Andric              Tok.is(AsmToken::Identifier)) {
23945f757f3fSDimitry Andric     if (DotDispStr.ends_with(".")) {
2395e8d8bef9SDimitry Andric       TrailingDot = DotDispStr.substr(DotDispStr.size() - 1);
2396e8d8bef9SDimitry Andric       DotDispStr = DotDispStr.drop_back(1);
2397e8d8bef9SDimitry Andric     }
23985ffd83dbSDimitry Andric     const std::pair<StringRef, StringRef> BaseMember = DotDispStr.split('.');
23995ffd83dbSDimitry Andric     const StringRef Base = BaseMember.first, Member = BaseMember.second;
2400e8d8bef9SDimitry Andric     if (getParser().lookUpField(SM.getType(), DotDispStr, Info) &&
2401e8d8bef9SDimitry Andric         getParser().lookUpField(SM.getSymName(), DotDispStr, Info) &&
2402e8d8bef9SDimitry Andric         getParser().lookUpField(DotDispStr, Info) &&
24035ffd83dbSDimitry Andric         (!SemaCallback ||
2404e8d8bef9SDimitry Andric          SemaCallback->LookupInlineAsmField(Base, Member, Info.Offset)))
24050b57cec5SDimitry Andric       return Error(Tok.getLoc(), "Unable to lookup field reference!");
2406e8d8bef9SDimitry Andric   } else {
24070b57cec5SDimitry Andric     return Error(Tok.getLoc(), "Unexpected token type!");
2408e8d8bef9SDimitry Andric   }
24090b57cec5SDimitry Andric 
24100b57cec5SDimitry Andric   // Eat the DotExpression and update End
24110b57cec5SDimitry Andric   End = SMLoc::getFromPointer(DotDispStr.data());
24120b57cec5SDimitry Andric   const char *DotExprEndLoc = DotDispStr.data() + DotDispStr.size();
24130b57cec5SDimitry Andric   while (Tok.getLoc().getPointer() < DotExprEndLoc)
24140b57cec5SDimitry Andric     Lex();
2415e8d8bef9SDimitry Andric   if (!TrailingDot.empty())
2416e8d8bef9SDimitry Andric     getLexer().UnLex(AsmToken(AsmToken::Dot, TrailingDot));
2417e8d8bef9SDimitry Andric   SM.addImm(Info.Offset);
2418e8d8bef9SDimitry Andric   SM.setTypeInfo(Info.Type);
24190b57cec5SDimitry Andric   return false;
24200b57cec5SDimitry Andric }
24210b57cec5SDimitry Andric 
2422480093f4SDimitry Andric /// Parse the 'offset' operator.
2423480093f4SDimitry Andric /// This operator is used to specify the location of a given operand
ParseIntelOffsetOperator(const MCExpr * & Val,StringRef & ID,InlineAsmIdentifierInfo & Info,SMLoc & End)2424480093f4SDimitry Andric bool X86AsmParser::ParseIntelOffsetOperator(const MCExpr *&Val, StringRef &ID,
2425480093f4SDimitry Andric                                             InlineAsmIdentifierInfo &Info,
2426480093f4SDimitry Andric                                             SMLoc &End) {
2427480093f4SDimitry Andric   // Eat offset, mark start of identifier.
2428480093f4SDimitry Andric   SMLoc Start = Lex().getLoc();
2429480093f4SDimitry Andric   ID = getTok().getString();
24305ffd83dbSDimitry Andric   if (!isParsingMSInlineAsm()) {
2431480093f4SDimitry Andric     if ((getTok().isNot(AsmToken::Identifier) &&
2432480093f4SDimitry Andric          getTok().isNot(AsmToken::String)) ||
2433e8d8bef9SDimitry Andric         getParser().parsePrimaryExpr(Val, End, nullptr))
2434480093f4SDimitry Andric       return Error(Start, "unexpected token!");
2435480093f4SDimitry Andric   } else if (ParseIntelInlineAsmIdentifier(Val, ID, Info, false, End, true)) {
2436480093f4SDimitry Andric     return Error(Start, "unable to lookup expression");
2437480093f4SDimitry Andric   } else if (Info.isKind(InlineAsmIdentifierInfo::IK_EnumVal)) {
2438480093f4SDimitry Andric     return Error(Start, "offset operator cannot yet handle constants");
2439480093f4SDimitry Andric   }
2440480093f4SDimitry Andric   return false;
24410b57cec5SDimitry Andric }
24420b57cec5SDimitry Andric 
24430b57cec5SDimitry Andric // Query a candidate string for being an Intel assembly operator
24440b57cec5SDimitry Andric // Report back its kind, or IOK_INVALID if does not evaluated as a known one
IdentifyIntelInlineAsmOperator(StringRef Name)24450b57cec5SDimitry Andric unsigned X86AsmParser::IdentifyIntelInlineAsmOperator(StringRef Name) {
24460b57cec5SDimitry Andric   return StringSwitch<unsigned>(Name)
24470b57cec5SDimitry Andric     .Cases("TYPE","type",IOK_TYPE)
24480b57cec5SDimitry Andric     .Cases("SIZE","size",IOK_SIZE)
24490b57cec5SDimitry Andric     .Cases("LENGTH","length",IOK_LENGTH)
24500b57cec5SDimitry Andric     .Default(IOK_INVALID);
24510b57cec5SDimitry Andric }
24520b57cec5SDimitry Andric 
24530b57cec5SDimitry Andric /// Parse the 'LENGTH', 'TYPE' and 'SIZE' operators.  The LENGTH operator
24540b57cec5SDimitry Andric /// returns the number of elements in an array.  It returns the value 1 for
24550b57cec5SDimitry Andric /// non-array variables.  The SIZE operator returns the size of a C or C++
24560b57cec5SDimitry Andric /// variable.  A variable's size is the product of its LENGTH and TYPE.  The
24570b57cec5SDimitry Andric /// TYPE operator returns the size of a C or C++ type or variable. If the
24580b57cec5SDimitry Andric /// variable is an array, TYPE returns the size of a single element.
ParseIntelInlineAsmOperator(unsigned OpKind)24590b57cec5SDimitry Andric unsigned X86AsmParser::ParseIntelInlineAsmOperator(unsigned OpKind) {
24600b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
24610b57cec5SDimitry Andric   const AsmToken &Tok = Parser.getTok();
24620b57cec5SDimitry Andric   Parser.Lex(); // Eat operator.
24630b57cec5SDimitry Andric 
24640b57cec5SDimitry Andric   const MCExpr *Val = nullptr;
24650b57cec5SDimitry Andric   InlineAsmIdentifierInfo Info;
24660b57cec5SDimitry Andric   SMLoc Start = Tok.getLoc(), End;
24670b57cec5SDimitry Andric   StringRef Identifier = Tok.getString();
24680b57cec5SDimitry Andric   if (ParseIntelInlineAsmIdentifier(Val, Identifier, Info,
2469e8d8bef9SDimitry Andric                                     /*IsUnevaluatedOperand=*/true, End))
24700b57cec5SDimitry Andric     return 0;
24710b57cec5SDimitry Andric 
24720b57cec5SDimitry Andric   if (!Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {
24730b57cec5SDimitry Andric     Error(Start, "unable to lookup expression");
24740b57cec5SDimitry Andric     return 0;
24750b57cec5SDimitry Andric   }
24760b57cec5SDimitry Andric 
24770b57cec5SDimitry Andric   unsigned CVal = 0;
24780b57cec5SDimitry Andric   switch(OpKind) {
24790b57cec5SDimitry Andric   default: llvm_unreachable("Unexpected operand kind!");
24800b57cec5SDimitry Andric   case IOK_LENGTH: CVal = Info.Var.Length; break;
24810b57cec5SDimitry Andric   case IOK_SIZE: CVal = Info.Var.Size; break;
24820b57cec5SDimitry Andric   case IOK_TYPE: CVal = Info.Var.Type; break;
24830b57cec5SDimitry Andric   }
24840b57cec5SDimitry Andric 
24850b57cec5SDimitry Andric   return CVal;
24860b57cec5SDimitry Andric }
24870b57cec5SDimitry Andric 
2488e8d8bef9SDimitry Andric // Query a candidate string for being an Intel assembly operator
2489e8d8bef9SDimitry Andric // Report back its kind, or IOK_INVALID if does not evaluated as a known one
IdentifyMasmOperator(StringRef Name)2490e8d8bef9SDimitry Andric unsigned X86AsmParser::IdentifyMasmOperator(StringRef Name) {
2491e8d8bef9SDimitry Andric   return StringSwitch<unsigned>(Name.lower())
2492e8d8bef9SDimitry Andric       .Case("type", MOK_TYPE)
2493e8d8bef9SDimitry Andric       .Cases("size", "sizeof", MOK_SIZEOF)
2494e8d8bef9SDimitry Andric       .Cases("length", "lengthof", MOK_LENGTHOF)
2495e8d8bef9SDimitry Andric       .Default(MOK_INVALID);
2496e8d8bef9SDimitry Andric }
2497e8d8bef9SDimitry Andric 
2498e8d8bef9SDimitry Andric /// Parse the 'LENGTHOF', 'SIZEOF', and 'TYPE' operators.  The LENGTHOF operator
2499e8d8bef9SDimitry Andric /// returns the number of elements in an array.  It returns the value 1 for
2500e8d8bef9SDimitry Andric /// non-array variables.  The SIZEOF operator returns the size of a type or
2501e8d8bef9SDimitry Andric /// variable in bytes.  A variable's size is the product of its LENGTH and TYPE.
2502e8d8bef9SDimitry Andric /// The TYPE operator returns the size of a variable. If the variable is an
2503e8d8bef9SDimitry Andric /// array, TYPE returns the size of a single element.
ParseMasmOperator(unsigned OpKind,int64_t & Val)2504e8d8bef9SDimitry Andric bool X86AsmParser::ParseMasmOperator(unsigned OpKind, int64_t &Val) {
2505e8d8bef9SDimitry Andric   MCAsmParser &Parser = getParser();
2506e8d8bef9SDimitry Andric   SMLoc OpLoc = Parser.getTok().getLoc();
2507e8d8bef9SDimitry Andric   Parser.Lex(); // Eat operator.
2508e8d8bef9SDimitry Andric 
2509e8d8bef9SDimitry Andric   Val = 0;
2510e8d8bef9SDimitry Andric   if (OpKind == MOK_SIZEOF || OpKind == MOK_TYPE) {
2511e8d8bef9SDimitry Andric     // Check for SIZEOF(<type>) and TYPE(<type>).
2512e8d8bef9SDimitry Andric     bool InParens = Parser.getTok().is(AsmToken::LParen);
2513e8d8bef9SDimitry Andric     const AsmToken &IDTok = InParens ? getLexer().peekTok() : Parser.getTok();
2514e8d8bef9SDimitry Andric     AsmTypeInfo Type;
2515e8d8bef9SDimitry Andric     if (IDTok.is(AsmToken::Identifier) &&
2516e8d8bef9SDimitry Andric         !Parser.lookUpType(IDTok.getIdentifier(), Type)) {
2517e8d8bef9SDimitry Andric       Val = Type.Size;
2518e8d8bef9SDimitry Andric 
2519e8d8bef9SDimitry Andric       // Eat tokens.
2520e8d8bef9SDimitry Andric       if (InParens)
2521e8d8bef9SDimitry Andric         parseToken(AsmToken::LParen);
2522e8d8bef9SDimitry Andric       parseToken(AsmToken::Identifier);
2523e8d8bef9SDimitry Andric       if (InParens)
2524e8d8bef9SDimitry Andric         parseToken(AsmToken::RParen);
2525e8d8bef9SDimitry Andric     }
2526e8d8bef9SDimitry Andric   }
2527e8d8bef9SDimitry Andric 
2528e8d8bef9SDimitry Andric   if (!Val) {
2529e8d8bef9SDimitry Andric     IntelExprStateMachine SM;
2530e8d8bef9SDimitry Andric     SMLoc End, Start = Parser.getTok().getLoc();
2531e8d8bef9SDimitry Andric     if (ParseIntelExpression(SM, End))
2532e8d8bef9SDimitry Andric       return true;
2533e8d8bef9SDimitry Andric 
2534e8d8bef9SDimitry Andric     switch (OpKind) {
2535e8d8bef9SDimitry Andric     default:
2536e8d8bef9SDimitry Andric       llvm_unreachable("Unexpected operand kind!");
2537e8d8bef9SDimitry Andric     case MOK_SIZEOF:
2538e8d8bef9SDimitry Andric       Val = SM.getSize();
2539e8d8bef9SDimitry Andric       break;
2540e8d8bef9SDimitry Andric     case MOK_LENGTHOF:
2541e8d8bef9SDimitry Andric       Val = SM.getLength();
2542e8d8bef9SDimitry Andric       break;
2543e8d8bef9SDimitry Andric     case MOK_TYPE:
2544e8d8bef9SDimitry Andric       Val = SM.getElementSize();
2545e8d8bef9SDimitry Andric       break;
2546e8d8bef9SDimitry Andric     }
2547e8d8bef9SDimitry Andric 
2548e8d8bef9SDimitry Andric     if (!Val)
2549e8d8bef9SDimitry Andric       return Error(OpLoc, "expression has unknown type", SMRange(Start, End));
2550e8d8bef9SDimitry Andric   }
2551e8d8bef9SDimitry Andric 
2552e8d8bef9SDimitry Andric   return false;
2553e8d8bef9SDimitry Andric }
2554e8d8bef9SDimitry Andric 
ParseIntelMemoryOperandSize(unsigned & Size)25550b57cec5SDimitry Andric bool X86AsmParser::ParseIntelMemoryOperandSize(unsigned &Size) {
25560b57cec5SDimitry Andric   Size = StringSwitch<unsigned>(getTok().getString())
25570b57cec5SDimitry Andric     .Cases("BYTE", "byte", 8)
25580b57cec5SDimitry Andric     .Cases("WORD", "word", 16)
25590b57cec5SDimitry Andric     .Cases("DWORD", "dword", 32)
25600b57cec5SDimitry Andric     .Cases("FLOAT", "float", 32)
25610b57cec5SDimitry Andric     .Cases("LONG", "long", 32)
25620b57cec5SDimitry Andric     .Cases("FWORD", "fword", 48)
25630b57cec5SDimitry Andric     .Cases("DOUBLE", "double", 64)
25640b57cec5SDimitry Andric     .Cases("QWORD", "qword", 64)
25650b57cec5SDimitry Andric     .Cases("MMWORD","mmword", 64)
25660b57cec5SDimitry Andric     .Cases("XWORD", "xword", 80)
25670b57cec5SDimitry Andric     .Cases("TBYTE", "tbyte", 80)
25680b57cec5SDimitry Andric     .Cases("XMMWORD", "xmmword", 128)
25690b57cec5SDimitry Andric     .Cases("YMMWORD", "ymmword", 256)
25700b57cec5SDimitry Andric     .Cases("ZMMWORD", "zmmword", 512)
25710b57cec5SDimitry Andric     .Default(0);
25720b57cec5SDimitry Andric   if (Size) {
25730b57cec5SDimitry Andric     const AsmToken &Tok = Lex(); // Eat operand size (e.g., byte, word).
25740fca6ea1SDimitry Andric     if (!(Tok.getString() == "PTR" || Tok.getString() == "ptr"))
25750b57cec5SDimitry Andric       return Error(Tok.getLoc(), "Expected 'PTR' or 'ptr' token!");
25760b57cec5SDimitry Andric     Lex(); // Eat ptr.
25770b57cec5SDimitry Andric   }
25780b57cec5SDimitry Andric   return false;
25790b57cec5SDimitry Andric }
25800b57cec5SDimitry Andric 
parseIntelOperand(OperandVector & Operands,StringRef Name)258181ad6265SDimitry Andric bool X86AsmParser::parseIntelOperand(OperandVector &Operands, StringRef Name) {
25820b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
25830b57cec5SDimitry Andric   const AsmToken &Tok = Parser.getTok();
25840b57cec5SDimitry Andric   SMLoc Start, End;
25850b57cec5SDimitry Andric 
25860b57cec5SDimitry Andric   // Parse optional Size directive.
25870b57cec5SDimitry Andric   unsigned Size;
25880b57cec5SDimitry Andric   if (ParseIntelMemoryOperandSize(Size))
2589e8d8bef9SDimitry Andric     return true;
25900b57cec5SDimitry Andric   bool PtrInOperand = bool(Size);
25910b57cec5SDimitry Andric 
25920b57cec5SDimitry Andric   Start = Tok.getLoc();
25930b57cec5SDimitry Andric 
25940b57cec5SDimitry Andric   // Rounding mode operand.
25950b57cec5SDimitry Andric   if (getLexer().is(AsmToken::LCurly))
2596e8d8bef9SDimitry Andric     return ParseRoundingModeOp(Start, Operands);
25970b57cec5SDimitry Andric 
25980b57cec5SDimitry Andric   // Register operand.
2599bdd1243dSDimitry Andric   MCRegister RegNo;
2600bdd1243dSDimitry Andric   if (Tok.is(AsmToken::Identifier) && !parseRegister(RegNo, Start, End)) {
26010b57cec5SDimitry Andric     if (RegNo == X86::RIP)
2602e8d8bef9SDimitry Andric       return Error(Start, "rip can only be used as a base register");
26030b57cec5SDimitry Andric     // A Register followed by ':' is considered a segment override
2604e8d8bef9SDimitry Andric     if (Tok.isNot(AsmToken::Colon)) {
2605e8d8bef9SDimitry Andric       if (PtrInOperand)
2606e8d8bef9SDimitry Andric         return Error(Start, "expected memory operand after 'ptr', "
26070b57cec5SDimitry Andric                             "found register operand instead");
2608e8d8bef9SDimitry Andric       Operands.push_back(X86Operand::CreateReg(RegNo, Start, End));
2609e8d8bef9SDimitry Andric       return false;
2610e8d8bef9SDimitry Andric     }
26110b57cec5SDimitry Andric     // An alleged segment override. check if we have a valid segment register
26120b57cec5SDimitry Andric     if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo))
2613e8d8bef9SDimitry Andric       return Error(Start, "invalid segment register");
26140b57cec5SDimitry Andric     // Eat ':' and update Start location
26150b57cec5SDimitry Andric     Start = Lex().getLoc();
26160b57cec5SDimitry Andric   }
26170b57cec5SDimitry Andric 
26180b57cec5SDimitry Andric   // Immediates and Memory
26190b57cec5SDimitry Andric   IntelExprStateMachine SM;
26200b57cec5SDimitry Andric   if (ParseIntelExpression(SM, End))
2621e8d8bef9SDimitry Andric     return true;
26220b57cec5SDimitry Andric 
26235ffd83dbSDimitry Andric   if (isParsingMSInlineAsm())
26240b57cec5SDimitry Andric     RewriteIntelExpression(SM, Start, Tok.getLoc());
26250b57cec5SDimitry Andric 
26260b57cec5SDimitry Andric   int64_t Imm = SM.getImm();
26270b57cec5SDimitry Andric   const MCExpr *Disp = SM.getSym();
26280b57cec5SDimitry Andric   const MCExpr *ImmDisp = MCConstantExpr::create(Imm, getContext());
26290b57cec5SDimitry Andric   if (Disp && Imm)
26300b57cec5SDimitry Andric     Disp = MCBinaryExpr::createAdd(Disp, ImmDisp, getContext());
26310b57cec5SDimitry Andric   if (!Disp)
26320b57cec5SDimitry Andric     Disp = ImmDisp;
26330b57cec5SDimitry Andric 
26340b57cec5SDimitry Andric   // RegNo != 0 specifies a valid segment register,
26350b57cec5SDimitry Andric   // and we are parsing a segment override
2636480093f4SDimitry Andric   if (!SM.isMemExpr() && !RegNo) {
26375ffd83dbSDimitry Andric     if (isParsingMSInlineAsm() && SM.isOffsetOperator()) {
2638e8d8bef9SDimitry Andric       const InlineAsmIdentifierInfo &Info = SM.getIdentifierInfo();
2639480093f4SDimitry Andric       if (Info.isKind(InlineAsmIdentifierInfo::IK_Var)) {
2640480093f4SDimitry Andric         // Disp includes the address of a variable; make sure this is recorded
2641480093f4SDimitry Andric         // for later handling.
2642e8d8bef9SDimitry Andric         Operands.push_back(X86Operand::CreateImm(Disp, Start, End,
2643e8d8bef9SDimitry Andric                                                  SM.getSymName(), Info.Var.Decl,
2644e8d8bef9SDimitry Andric                                                  Info.Var.IsGlobalLV));
2645e8d8bef9SDimitry Andric         return false;
2646480093f4SDimitry Andric       }
2647480093f4SDimitry Andric     }
2648480093f4SDimitry Andric 
2649e8d8bef9SDimitry Andric     Operands.push_back(X86Operand::CreateImm(Disp, Start, End));
2650e8d8bef9SDimitry Andric     return false;
2651480093f4SDimitry Andric   }
26520b57cec5SDimitry Andric 
26530b57cec5SDimitry Andric   StringRef ErrMsg;
26540b57cec5SDimitry Andric   unsigned BaseReg = SM.getBaseReg();
26550b57cec5SDimitry Andric   unsigned IndexReg = SM.getIndexReg();
265681ad6265SDimitry Andric   if (IndexReg && BaseReg == X86::RIP)
265781ad6265SDimitry Andric     BaseReg = 0;
26580b57cec5SDimitry Andric   unsigned Scale = SM.getScale();
2659e8d8bef9SDimitry Andric   if (!PtrInOperand)
2660e8d8bef9SDimitry Andric     Size = SM.getElementSize() << 3;
26610b57cec5SDimitry Andric 
26620b57cec5SDimitry Andric   if (Scale == 0 && BaseReg != X86::ESP && BaseReg != X86::RSP &&
26630b57cec5SDimitry Andric       (IndexReg == X86::ESP || IndexReg == X86::RSP))
26640b57cec5SDimitry Andric     std::swap(BaseReg, IndexReg);
26650b57cec5SDimitry Andric 
26660b57cec5SDimitry Andric   // If BaseReg is a vector register and IndexReg is not, swap them unless
26670b57cec5SDimitry Andric   // Scale was specified in which case it would be an error.
26680b57cec5SDimitry Andric   if (Scale == 0 &&
26690b57cec5SDimitry Andric       !(X86MCRegisterClasses[X86::VR128XRegClassID].contains(IndexReg) ||
26700b57cec5SDimitry Andric         X86MCRegisterClasses[X86::VR256XRegClassID].contains(IndexReg) ||
26710b57cec5SDimitry Andric         X86MCRegisterClasses[X86::VR512RegClassID].contains(IndexReg)) &&
26720b57cec5SDimitry Andric       (X86MCRegisterClasses[X86::VR128XRegClassID].contains(BaseReg) ||
26730b57cec5SDimitry Andric        X86MCRegisterClasses[X86::VR256XRegClassID].contains(BaseReg) ||
26740b57cec5SDimitry Andric        X86MCRegisterClasses[X86::VR512RegClassID].contains(BaseReg)))
26750b57cec5SDimitry Andric     std::swap(BaseReg, IndexReg);
26760b57cec5SDimitry Andric 
26770b57cec5SDimitry Andric   if (Scale != 0 &&
26780b57cec5SDimitry Andric       X86MCRegisterClasses[X86::GR16RegClassID].contains(IndexReg))
2679e8d8bef9SDimitry Andric     return Error(Start, "16-bit addresses cannot have a scale");
26800b57cec5SDimitry Andric 
26810b57cec5SDimitry Andric   // If there was no explicit scale specified, change it to 1.
26820b57cec5SDimitry Andric   if (Scale == 0)
26830b57cec5SDimitry Andric     Scale = 1;
26840b57cec5SDimitry Andric 
26850b57cec5SDimitry Andric   // If this is a 16-bit addressing mode with the base and index in the wrong
26860b57cec5SDimitry Andric   // order, swap them so CheckBaseRegAndIndexRegAndScale doesn't fail. It is
26870b57cec5SDimitry Andric   // shared with att syntax where order matters.
26880b57cec5SDimitry Andric   if ((BaseReg == X86::SI || BaseReg == X86::DI) &&
26890b57cec5SDimitry Andric       (IndexReg == X86::BX || IndexReg == X86::BP))
26900b57cec5SDimitry Andric     std::swap(BaseReg, IndexReg);
26910b57cec5SDimitry Andric 
26920b57cec5SDimitry Andric   if ((BaseReg || IndexReg) &&
26930b57cec5SDimitry Andric       CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
26940b57cec5SDimitry Andric                                       ErrMsg))
2695e8d8bef9SDimitry Andric     return Error(Start, ErrMsg);
26965f757f3fSDimitry Andric   bool IsUnconditionalBranch =
26975f757f3fSDimitry Andric       Name.equals_insensitive("jmp") || Name.equals_insensitive("call");
26985ffd83dbSDimitry Andric   if (isParsingMSInlineAsm())
26995f757f3fSDimitry Andric     return CreateMemForMSInlineAsm(RegNo, Disp, BaseReg, IndexReg, Scale,
27005f757f3fSDimitry Andric                                    IsUnconditionalBranch && is64BitMode(),
27015f757f3fSDimitry Andric                                    Start, End, Size, SM.getSymName(),
2702e8d8bef9SDimitry Andric                                    SM.getIdentifierInfo(), Operands);
27035ffd83dbSDimitry Andric 
2704fe6060f1SDimitry Andric   // When parsing x64 MS-style assembly, all non-absolute references to a named
2705fe6060f1SDimitry Andric   // variable default to RIP-relative.
270681ad6265SDimitry Andric   unsigned DefaultBaseReg = X86::NoRegister;
270781ad6265SDimitry Andric   bool MaybeDirectBranchDest = true;
270881ad6265SDimitry Andric 
270906c3fb27SDimitry Andric   if (Parser.isParsingMasm()) {
2710*6e516c87SDimitry Andric     if (is64BitMode() &&
2711*6e516c87SDimitry Andric         ((PtrInOperand && !IndexReg) || SM.getElementSize() > 0)) {
271281ad6265SDimitry Andric       DefaultBaseReg = X86::RIP;
271381ad6265SDimitry Andric     }
271481ad6265SDimitry Andric     if (IsUnconditionalBranch) {
271581ad6265SDimitry Andric       if (PtrInOperand) {
271681ad6265SDimitry Andric         MaybeDirectBranchDest = false;
271781ad6265SDimitry Andric         if (is64BitMode())
271881ad6265SDimitry Andric           DefaultBaseReg = X86::RIP;
271981ad6265SDimitry Andric       } else if (!BaseReg && !IndexReg && Disp &&
272081ad6265SDimitry Andric                  Disp->getKind() == MCExpr::SymbolRef) {
272181ad6265SDimitry Andric         if (is64BitMode()) {
272281ad6265SDimitry Andric           if (SM.getSize() == 8) {
272381ad6265SDimitry Andric             MaybeDirectBranchDest = false;
272481ad6265SDimitry Andric             DefaultBaseReg = X86::RIP;
272581ad6265SDimitry Andric           }
272681ad6265SDimitry Andric         } else {
272781ad6265SDimitry Andric           if (SM.getSize() == 4 || SM.getSize() == 2)
272881ad6265SDimitry Andric             MaybeDirectBranchDest = false;
272981ad6265SDimitry Andric         }
273081ad6265SDimitry Andric       }
273181ad6265SDimitry Andric     }
273206c3fb27SDimitry Andric   } else if (IsUnconditionalBranch) {
273306c3fb27SDimitry Andric     // Treat `call [offset fn_ref]` (or `jmp`) syntax as an error.
273406c3fb27SDimitry Andric     if (!PtrInOperand && SM.isOffsetOperator())
273506c3fb27SDimitry Andric       return Error(
273606c3fb27SDimitry Andric           Start, "`OFFSET` operator cannot be used in an unconditional branch");
273706c3fb27SDimitry Andric     if (PtrInOperand || SM.isBracketUsed())
273806c3fb27SDimitry Andric       MaybeDirectBranchDest = false;
27390b57cec5SDimitry Andric   }
27400b57cec5SDimitry Andric 
274181ad6265SDimitry Andric   if ((BaseReg || IndexReg || RegNo || DefaultBaseReg != X86::NoRegister))
274281ad6265SDimitry Andric     Operands.push_back(X86Operand::CreateMem(
274381ad6265SDimitry Andric         getPointerWidth(), RegNo, Disp, BaseReg, IndexReg, Scale, Start, End,
274481ad6265SDimitry Andric         Size, DefaultBaseReg, /*SymName=*/StringRef(), /*OpDecl=*/nullptr,
274581ad6265SDimitry Andric         /*FrontendSize=*/0, /*UseUpRegs=*/false, MaybeDirectBranchDest));
2746e8d8bef9SDimitry Andric   else
274781ad6265SDimitry Andric     Operands.push_back(X86Operand::CreateMem(
274881ad6265SDimitry Andric         getPointerWidth(), Disp, Start, End, Size, /*SymName=*/StringRef(),
274981ad6265SDimitry Andric         /*OpDecl=*/nullptr, /*FrontendSize=*/0, /*UseUpRegs=*/false,
275081ad6265SDimitry Andric         MaybeDirectBranchDest));
2751e8d8bef9SDimitry Andric   return false;
2752e8d8bef9SDimitry Andric }
2753e8d8bef9SDimitry Andric 
parseATTOperand(OperandVector & Operands)275481ad6265SDimitry Andric bool X86AsmParser::parseATTOperand(OperandVector &Operands) {
27550b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
27560b57cec5SDimitry Andric   switch (getLexer().getKind()) {
27570b57cec5SDimitry Andric   case AsmToken::Dollar: {
27580b57cec5SDimitry Andric     // $42 or $ID -> immediate.
27590b57cec5SDimitry Andric     SMLoc Start = Parser.getTok().getLoc(), End;
27600b57cec5SDimitry Andric     Parser.Lex();
27610b57cec5SDimitry Andric     const MCExpr *Val;
27620b57cec5SDimitry Andric     // This is an immediate, so we should not parse a register. Do a precheck
27630b57cec5SDimitry Andric     // for '%' to supercede intra-register parse errors.
27640b57cec5SDimitry Andric     SMLoc L = Parser.getTok().getLoc();
27650b57cec5SDimitry Andric     if (check(getLexer().is(AsmToken::Percent), L,
27660b57cec5SDimitry Andric               "expected immediate expression") ||
27670b57cec5SDimitry Andric         getParser().parseExpression(Val, End) ||
27680b57cec5SDimitry Andric         check(isa<X86MCExpr>(Val), L, "expected immediate expression"))
2769e8d8bef9SDimitry Andric       return true;
2770e8d8bef9SDimitry Andric     Operands.push_back(X86Operand::CreateImm(Val, Start, End));
2771e8d8bef9SDimitry Andric     return false;
27720b57cec5SDimitry Andric   }
27730b57cec5SDimitry Andric   case AsmToken::LCurly: {
27740b57cec5SDimitry Andric     SMLoc Start = Parser.getTok().getLoc();
2775e8d8bef9SDimitry Andric     return ParseRoundingModeOp(Start, Operands);
27760b57cec5SDimitry Andric   }
27770b57cec5SDimitry Andric   default: {
27780b57cec5SDimitry Andric     // This a memory operand or a register. We have some parsing complications
27790b57cec5SDimitry Andric     // as a '(' may be part of an immediate expression or the addressing mode
27800b57cec5SDimitry Andric     // block. This is complicated by the fact that an assembler-level variable
27810b57cec5SDimitry Andric     // may refer either to a register or an immediate expression.
27820b57cec5SDimitry Andric 
27830b57cec5SDimitry Andric     SMLoc Loc = Parser.getTok().getLoc(), EndLoc;
27840b57cec5SDimitry Andric     const MCExpr *Expr = nullptr;
27850b57cec5SDimitry Andric     unsigned Reg = 0;
27860b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::LParen)) {
27870b57cec5SDimitry Andric       // No '(' so this is either a displacement expression or a register.
27880b57cec5SDimitry Andric       if (Parser.parseExpression(Expr, EndLoc))
2789e8d8bef9SDimitry Andric         return true;
27900b57cec5SDimitry Andric       if (auto *RE = dyn_cast<X86MCExpr>(Expr)) {
27910b57cec5SDimitry Andric         // Segment Register. Reset Expr and copy value to register.
27920b57cec5SDimitry Andric         Expr = nullptr;
27930b57cec5SDimitry Andric         Reg = RE->getRegNo();
27940b57cec5SDimitry Andric 
2795349cc55cSDimitry Andric         // Check the register.
27960b57cec5SDimitry Andric         if (Reg == X86::EIZ || Reg == X86::RIZ)
2797e8d8bef9SDimitry Andric           return Error(
27980b57cec5SDimitry Andric               Loc, "%eiz and %riz can only be used as index registers",
27990b57cec5SDimitry Andric               SMRange(Loc, EndLoc));
28000b57cec5SDimitry Andric         if (Reg == X86::RIP)
2801e8d8bef9SDimitry Andric           return Error(Loc, "%rip can only be used as a base register",
28020b57cec5SDimitry Andric                        SMRange(Loc, EndLoc));
28030b57cec5SDimitry Andric         // Return register that are not segment prefixes immediately.
2804e8d8bef9SDimitry Andric         if (!Parser.parseOptionalToken(AsmToken::Colon)) {
2805e8d8bef9SDimitry Andric           Operands.push_back(X86Operand::CreateReg(Reg, Loc, EndLoc));
2806e8d8bef9SDimitry Andric           return false;
2807e8d8bef9SDimitry Andric         }
28080b57cec5SDimitry Andric         if (!X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(Reg))
2809e8d8bef9SDimitry Andric           return Error(Loc, "invalid segment register");
2810e8d8bef9SDimitry Andric         // Accept a '*' absolute memory reference after the segment. Place it
2811e8d8bef9SDimitry Andric         // before the full memory operand.
2812e8d8bef9SDimitry Andric         if (getLexer().is(AsmToken::Star))
2813e8d8bef9SDimitry Andric           Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
28140b57cec5SDimitry Andric       }
28150b57cec5SDimitry Andric     }
28160b57cec5SDimitry Andric     // This is a Memory operand.
2817e8d8bef9SDimitry Andric     return ParseMemOperand(Reg, Expr, Loc, EndLoc, Operands);
28180b57cec5SDimitry Andric   }
28190b57cec5SDimitry Andric   }
28200b57cec5SDimitry Andric }
28210b57cec5SDimitry Andric 
28220b57cec5SDimitry Andric // X86::COND_INVALID if not a recognized condition code or alternate mnemonic,
28230b57cec5SDimitry Andric // otherwise the EFLAGS Condition Code enumerator.
ParseConditionCode(StringRef CC)28240b57cec5SDimitry Andric X86::CondCode X86AsmParser::ParseConditionCode(StringRef CC) {
28250b57cec5SDimitry Andric   return StringSwitch<X86::CondCode>(CC)
28260b57cec5SDimitry Andric       .Case("o", X86::COND_O)          // Overflow
28270b57cec5SDimitry Andric       .Case("no", X86::COND_NO)        // No Overflow
28280b57cec5SDimitry Andric       .Cases("b", "nae", X86::COND_B)  // Below/Neither Above nor Equal
28290b57cec5SDimitry Andric       .Cases("ae", "nb", X86::COND_AE) // Above or Equal/Not Below
28300b57cec5SDimitry Andric       .Cases("e", "z", X86::COND_E)    // Equal/Zero
28310b57cec5SDimitry Andric       .Cases("ne", "nz", X86::COND_NE) // Not Equal/Not Zero
28320b57cec5SDimitry Andric       .Cases("be", "na", X86::COND_BE) // Below or Equal/Not Above
28330b57cec5SDimitry Andric       .Cases("a", "nbe", X86::COND_A)  // Above/Neither Below nor Equal
28340b57cec5SDimitry Andric       .Case("s", X86::COND_S)          // Sign
28350b57cec5SDimitry Andric       .Case("ns", X86::COND_NS)        // No Sign
28360b57cec5SDimitry Andric       .Cases("p", "pe", X86::COND_P)   // Parity/Parity Even
28370b57cec5SDimitry Andric       .Cases("np", "po", X86::COND_NP) // No Parity/Parity Odd
28380b57cec5SDimitry Andric       .Cases("l", "nge", X86::COND_L)  // Less/Neither Greater nor Equal
28390b57cec5SDimitry Andric       .Cases("ge", "nl", X86::COND_GE) // Greater or Equal/Not Less
28400b57cec5SDimitry Andric       .Cases("le", "ng", X86::COND_LE) // Less or Equal/Not Greater
28410b57cec5SDimitry Andric       .Cases("g", "nle", X86::COND_G)  // Greater/Neither Less nor Equal
28420b57cec5SDimitry Andric       .Default(X86::COND_INVALID);
28430b57cec5SDimitry Andric }
28440b57cec5SDimitry Andric 
28450b57cec5SDimitry Andric // true on failure, false otherwise
28460b57cec5SDimitry Andric // If no {z} mark was found - Parser doesn't advance
ParseZ(std::unique_ptr<X86Operand> & Z,const SMLoc & StartLoc)28470b57cec5SDimitry Andric bool X86AsmParser::ParseZ(std::unique_ptr<X86Operand> &Z,
28480b57cec5SDimitry Andric                           const SMLoc &StartLoc) {
28490b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
28500b57cec5SDimitry Andric   // Assuming we are just pass the '{' mark, quering the next token
28510b57cec5SDimitry Andric   // Searched for {z}, but none was found. Return false, as no parsing error was
28520b57cec5SDimitry Andric   // encountered
28530b57cec5SDimitry Andric   if (!(getLexer().is(AsmToken::Identifier) &&
28540b57cec5SDimitry Andric         (getLexer().getTok().getIdentifier() == "z")))
28550b57cec5SDimitry Andric     return false;
28560b57cec5SDimitry Andric   Parser.Lex(); // Eat z
28570b57cec5SDimitry Andric   // Query and eat the '}' mark
28580b57cec5SDimitry Andric   if (!getLexer().is(AsmToken::RCurly))
28590b57cec5SDimitry Andric     return Error(getLexer().getLoc(), "Expected } at this point");
28600b57cec5SDimitry Andric   Parser.Lex(); // Eat '}'
286181ad6265SDimitry Andric   // Assign Z with the {z} mark operand
28620b57cec5SDimitry Andric   Z = X86Operand::CreateToken("{z}", StartLoc);
28630b57cec5SDimitry Andric   return false;
28640b57cec5SDimitry Andric }
28650b57cec5SDimitry Andric 
28660b57cec5SDimitry Andric // true on failure, false otherwise
HandleAVX512Operand(OperandVector & Operands)2867e8d8bef9SDimitry Andric bool X86AsmParser::HandleAVX512Operand(OperandVector &Operands) {
28680b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
28690b57cec5SDimitry Andric   if (getLexer().is(AsmToken::LCurly)) {
28700b57cec5SDimitry Andric     // Eat "{" and mark the current place.
28710b57cec5SDimitry Andric     const SMLoc consumedToken = consumeToken();
28720b57cec5SDimitry Andric     // Distinguish {1to<NUM>} from {%k<NUM>}.
28730b57cec5SDimitry Andric     if(getLexer().is(AsmToken::Integer)) {
28740b57cec5SDimitry Andric       // Parse memory broadcasting ({1to<NUM>}).
28750b57cec5SDimitry Andric       if (getLexer().getTok().getIntVal() != 1)
28760b57cec5SDimitry Andric         return TokError("Expected 1to<NUM> at this point");
2877e8d8bef9SDimitry Andric       StringRef Prefix = getLexer().getTok().getString();
2878e8d8bef9SDimitry Andric       Parser.Lex(); // Eat first token of 1to8
2879e8d8bef9SDimitry Andric       if (!getLexer().is(AsmToken::Identifier))
28800b57cec5SDimitry Andric         return TokError("Expected 1to<NUM> at this point");
28810b57cec5SDimitry Andric       // Recognize only reasonable suffixes.
2882e8d8bef9SDimitry Andric       SmallVector<char, 5> BroadcastVector;
2883e8d8bef9SDimitry Andric       StringRef BroadcastString = (Prefix + getLexer().getTok().getIdentifier())
2884e8d8bef9SDimitry Andric                                       .toStringRef(BroadcastVector);
28855f757f3fSDimitry Andric       if (!BroadcastString.starts_with("1to"))
2886e8d8bef9SDimitry Andric         return TokError("Expected 1to<NUM> at this point");
28870b57cec5SDimitry Andric       const char *BroadcastPrimitive =
2888e8d8bef9SDimitry Andric           StringSwitch<const char *>(BroadcastString)
2889e8d8bef9SDimitry Andric               .Case("1to2", "{1to2}")
2890e8d8bef9SDimitry Andric               .Case("1to4", "{1to4}")
2891e8d8bef9SDimitry Andric               .Case("1to8", "{1to8}")
2892e8d8bef9SDimitry Andric               .Case("1to16", "{1to16}")
2893349cc55cSDimitry Andric               .Case("1to32", "{1to32}")
28940b57cec5SDimitry Andric               .Default(nullptr);
28950b57cec5SDimitry Andric       if (!BroadcastPrimitive)
28960b57cec5SDimitry Andric         return TokError("Invalid memory broadcast primitive.");
2897e8d8bef9SDimitry Andric       Parser.Lex(); // Eat trailing token of 1toN
28980b57cec5SDimitry Andric       if (!getLexer().is(AsmToken::RCurly))
28990b57cec5SDimitry Andric         return TokError("Expected } at this point");
29000b57cec5SDimitry Andric       Parser.Lex();  // Eat "}"
29010b57cec5SDimitry Andric       Operands.push_back(X86Operand::CreateToken(BroadcastPrimitive,
29020b57cec5SDimitry Andric                                                  consumedToken));
29030b57cec5SDimitry Andric       // No AVX512 specific primitives can pass
29040b57cec5SDimitry Andric       // after memory broadcasting, so return.
29050b57cec5SDimitry Andric       return false;
29060b57cec5SDimitry Andric     } else {
29070b57cec5SDimitry Andric       // Parse either {k}{z}, {z}{k}, {k} or {z}
29080b57cec5SDimitry Andric       // last one have no meaning, but GCC accepts it
29090b57cec5SDimitry Andric       // Currently, we're just pass a '{' mark
29100b57cec5SDimitry Andric       std::unique_ptr<X86Operand> Z;
29110b57cec5SDimitry Andric       if (ParseZ(Z, consumedToken))
29120b57cec5SDimitry Andric         return true;
29130b57cec5SDimitry Andric       // Reaching here means that parsing of the allegadly '{z}' mark yielded
29140b57cec5SDimitry Andric       // no errors.
29150b57cec5SDimitry Andric       // Query for the need of further parsing for a {%k<NUM>} mark
29160b57cec5SDimitry Andric       if (!Z || getLexer().is(AsmToken::LCurly)) {
29170b57cec5SDimitry Andric         SMLoc StartLoc = Z ? consumeToken() : consumedToken;
29180b57cec5SDimitry Andric         // Parse an op-mask register mark ({%k<NUM>}), which is now to be
29190b57cec5SDimitry Andric         // expected
2920bdd1243dSDimitry Andric         MCRegister RegNo;
29210b57cec5SDimitry Andric         SMLoc RegLoc;
2922bdd1243dSDimitry Andric         if (!parseRegister(RegNo, RegLoc, StartLoc) &&
29230b57cec5SDimitry Andric             X86MCRegisterClasses[X86::VK1RegClassID].contains(RegNo)) {
29240b57cec5SDimitry Andric           if (RegNo == X86::K0)
29250b57cec5SDimitry Andric             return Error(RegLoc, "Register k0 can't be used as write mask");
29260b57cec5SDimitry Andric           if (!getLexer().is(AsmToken::RCurly))
29270b57cec5SDimitry Andric             return Error(getLexer().getLoc(), "Expected } at this point");
29280b57cec5SDimitry Andric           Operands.push_back(X86Operand::CreateToken("{", StartLoc));
29290b57cec5SDimitry Andric           Operands.push_back(
29300b57cec5SDimitry Andric               X86Operand::CreateReg(RegNo, StartLoc, StartLoc));
29310b57cec5SDimitry Andric           Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
29320b57cec5SDimitry Andric         } else
29330b57cec5SDimitry Andric           return Error(getLexer().getLoc(),
29340b57cec5SDimitry Andric                         "Expected an op-mask register at this point");
29350b57cec5SDimitry Andric         // {%k<NUM>} mark is found, inquire for {z}
29360b57cec5SDimitry Andric         if (getLexer().is(AsmToken::LCurly) && !Z) {
29370b57cec5SDimitry Andric           // Have we've found a parsing error, or found no (expected) {z} mark
29380b57cec5SDimitry Andric           // - report an error
29390b57cec5SDimitry Andric           if (ParseZ(Z, consumeToken()) || !Z)
29400b57cec5SDimitry Andric             return Error(getLexer().getLoc(),
29410b57cec5SDimitry Andric                          "Expected a {z} mark at this point");
29420b57cec5SDimitry Andric 
29430b57cec5SDimitry Andric         }
29440b57cec5SDimitry Andric         // '{z}' on its own is meaningless, hence should be ignored.
29450b57cec5SDimitry Andric         // on the contrary - have it been accompanied by a K register,
29460b57cec5SDimitry Andric         // allow it.
29470b57cec5SDimitry Andric         if (Z)
29480b57cec5SDimitry Andric           Operands.push_back(std::move(Z));
29490b57cec5SDimitry Andric       }
29500b57cec5SDimitry Andric     }
29510b57cec5SDimitry Andric   }
29520b57cec5SDimitry Andric   return false;
29530b57cec5SDimitry Andric }
29540b57cec5SDimitry Andric 
29550b57cec5SDimitry Andric /// ParseMemOperand: 'seg : disp(basereg, indexreg, scale)'.  The '%ds:' prefix
29560b57cec5SDimitry Andric /// has already been parsed if present. disp may be provided as well.
ParseMemOperand(unsigned SegReg,const MCExpr * Disp,SMLoc StartLoc,SMLoc EndLoc,OperandVector & Operands)2957e8d8bef9SDimitry Andric bool X86AsmParser::ParseMemOperand(unsigned SegReg, const MCExpr *Disp,
2958e8d8bef9SDimitry Andric                                    SMLoc StartLoc, SMLoc EndLoc,
2959e8d8bef9SDimitry Andric                                    OperandVector &Operands) {
29600b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
29610b57cec5SDimitry Andric   SMLoc Loc;
29620b57cec5SDimitry Andric   // Based on the initial passed values, we may be in any of these cases, we are
29630b57cec5SDimitry Andric   // in one of these cases (with current position (*)):
29640b57cec5SDimitry Andric 
29650b57cec5SDimitry Andric   //   1. seg : * disp  (base-index-scale-expr)
29660b57cec5SDimitry Andric   //   2. seg : *(disp) (base-index-scale-expr)
29670b57cec5SDimitry Andric   //   3. seg :       *(base-index-scale-expr)
29680b57cec5SDimitry Andric   //   4.        disp  *(base-index-scale-expr)
29690b57cec5SDimitry Andric   //   5.      *(disp)  (base-index-scale-expr)
29700b57cec5SDimitry Andric   //   6.             *(base-index-scale-expr)
29710b57cec5SDimitry Andric   //   7.  disp *
29720b57cec5SDimitry Andric   //   8. *(disp)
29730b57cec5SDimitry Andric 
29740b57cec5SDimitry Andric   // If we do not have an displacement yet, check if we're in cases 4 or 6 by
29750b57cec5SDimitry Andric   // checking if the first object after the parenthesis is a register (or an
29760b57cec5SDimitry Andric   // identifier referring to a register) and parse the displacement or default
29770b57cec5SDimitry Andric   // to 0 as appropriate.
29780b57cec5SDimitry Andric   auto isAtMemOperand = [this]() {
29790b57cec5SDimitry Andric     if (this->getLexer().isNot(AsmToken::LParen))
29800b57cec5SDimitry Andric       return false;
29810b57cec5SDimitry Andric     AsmToken Buf[2];
29820b57cec5SDimitry Andric     StringRef Id;
29830b57cec5SDimitry Andric     auto TokCount = this->getLexer().peekTokens(Buf, true);
29840b57cec5SDimitry Andric     if (TokCount == 0)
29850b57cec5SDimitry Andric       return false;
29860b57cec5SDimitry Andric     switch (Buf[0].getKind()) {
29870b57cec5SDimitry Andric     case AsmToken::Percent:
29880b57cec5SDimitry Andric     case AsmToken::Comma:
29890b57cec5SDimitry Andric       return true;
29900b57cec5SDimitry Andric     // These lower cases are doing a peekIdentifier.
29910b57cec5SDimitry Andric     case AsmToken::At:
29920b57cec5SDimitry Andric     case AsmToken::Dollar:
29930b57cec5SDimitry Andric       if ((TokCount > 1) &&
29940b57cec5SDimitry Andric           (Buf[1].is(AsmToken::Identifier) || Buf[1].is(AsmToken::String)) &&
29950b57cec5SDimitry Andric           (Buf[0].getLoc().getPointer() + 1 == Buf[1].getLoc().getPointer()))
29960b57cec5SDimitry Andric         Id = StringRef(Buf[0].getLoc().getPointer(),
29970b57cec5SDimitry Andric                        Buf[1].getIdentifier().size() + 1);
29980b57cec5SDimitry Andric       break;
29990b57cec5SDimitry Andric     case AsmToken::Identifier:
30000b57cec5SDimitry Andric     case AsmToken::String:
30010b57cec5SDimitry Andric       Id = Buf[0].getIdentifier();
30020b57cec5SDimitry Andric       break;
30030b57cec5SDimitry Andric     default:
30040b57cec5SDimitry Andric       return false;
30050b57cec5SDimitry Andric     }
30060b57cec5SDimitry Andric     // We have an ID. Check if it is bound to a register.
30070b57cec5SDimitry Andric     if (!Id.empty()) {
30080b57cec5SDimitry Andric       MCSymbol *Sym = this->getContext().getOrCreateSymbol(Id);
30090b57cec5SDimitry Andric       if (Sym->isVariable()) {
30100b57cec5SDimitry Andric         auto V = Sym->getVariableValue(/*SetUsed*/ false);
30110b57cec5SDimitry Andric         return isa<X86MCExpr>(V);
30120b57cec5SDimitry Andric       }
30130b57cec5SDimitry Andric     }
30140b57cec5SDimitry Andric     return false;
30150b57cec5SDimitry Andric   };
30160b57cec5SDimitry Andric 
30170b57cec5SDimitry Andric   if (!Disp) {
30180b57cec5SDimitry Andric     // Parse immediate if we're not at a mem operand yet.
30190b57cec5SDimitry Andric     if (!isAtMemOperand()) {
30200b57cec5SDimitry Andric       if (Parser.parseTokenLoc(Loc) || Parser.parseExpression(Disp, EndLoc))
3021e8d8bef9SDimitry Andric         return true;
30220b57cec5SDimitry Andric       assert(!isa<X86MCExpr>(Disp) && "Expected non-register here.");
30230b57cec5SDimitry Andric     } else {
30240b57cec5SDimitry Andric       // Disp is implicitly zero if we haven't parsed it yet.
30250b57cec5SDimitry Andric       Disp = MCConstantExpr::create(0, Parser.getContext());
30260b57cec5SDimitry Andric     }
30270b57cec5SDimitry Andric   }
30280b57cec5SDimitry Andric 
30290b57cec5SDimitry Andric   // We are now either at the end of the operand or at the '(' at the start of a
30300b57cec5SDimitry Andric   // base-index-scale-expr.
30310b57cec5SDimitry Andric 
30320b57cec5SDimitry Andric   if (!parseOptionalToken(AsmToken::LParen)) {
30330b57cec5SDimitry Andric     if (SegReg == 0)
3034e8d8bef9SDimitry Andric       Operands.push_back(
3035e8d8bef9SDimitry Andric           X86Operand::CreateMem(getPointerWidth(), Disp, StartLoc, EndLoc));
3036e8d8bef9SDimitry Andric     else
3037e8d8bef9SDimitry Andric       Operands.push_back(X86Operand::CreateMem(getPointerWidth(), SegReg, Disp,
3038e8d8bef9SDimitry Andric                                                0, 0, 1, StartLoc, EndLoc));
3039e8d8bef9SDimitry Andric     return false;
30400b57cec5SDimitry Andric   }
30410b57cec5SDimitry Andric 
30420b57cec5SDimitry Andric   // If we reached here, then eat the '(' and Process
30430b57cec5SDimitry Andric   // the rest of the memory operand.
30440b57cec5SDimitry Andric   unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
30450b57cec5SDimitry Andric   SMLoc BaseLoc = getLexer().getLoc();
30460b57cec5SDimitry Andric   const MCExpr *E;
30470b57cec5SDimitry Andric   StringRef ErrMsg;
30480b57cec5SDimitry Andric 
30490b57cec5SDimitry Andric   // Parse BaseReg if one is provided.
30500b57cec5SDimitry Andric   if (getLexer().isNot(AsmToken::Comma) && getLexer().isNot(AsmToken::RParen)) {
30510b57cec5SDimitry Andric     if (Parser.parseExpression(E, EndLoc) ||
30520b57cec5SDimitry Andric         check(!isa<X86MCExpr>(E), BaseLoc, "expected register here"))
3053e8d8bef9SDimitry Andric       return true;
30540b57cec5SDimitry Andric 
3055349cc55cSDimitry Andric     // Check the register.
30560b57cec5SDimitry Andric     BaseReg = cast<X86MCExpr>(E)->getRegNo();
30570b57cec5SDimitry Andric     if (BaseReg == X86::EIZ || BaseReg == X86::RIZ)
3058e8d8bef9SDimitry Andric       return Error(BaseLoc, "eiz and riz can only be used as index registers",
30590b57cec5SDimitry Andric                    SMRange(BaseLoc, EndLoc));
30600b57cec5SDimitry Andric   }
30610b57cec5SDimitry Andric 
30620b57cec5SDimitry Andric   if (parseOptionalToken(AsmToken::Comma)) {
30630b57cec5SDimitry Andric     // Following the comma we should have either an index register, or a scale
30640b57cec5SDimitry Andric     // value. We don't support the later form, but we want to parse it
30650b57cec5SDimitry Andric     // correctly.
30660b57cec5SDimitry Andric     //
30670b57cec5SDimitry Andric     // Even though it would be completely consistent to support syntax like
30680b57cec5SDimitry Andric     // "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
30690b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::RParen)) {
30700b57cec5SDimitry Andric       if (Parser.parseTokenLoc(Loc) || Parser.parseExpression(E, EndLoc))
3071e8d8bef9SDimitry Andric         return true;
30720b57cec5SDimitry Andric 
30730b57cec5SDimitry Andric       if (!isa<X86MCExpr>(E)) {
30740b57cec5SDimitry Andric         // We've parsed an unexpected Scale Value instead of an index
30750b57cec5SDimitry Andric         // register. Interpret it as an absolute.
30760b57cec5SDimitry Andric         int64_t ScaleVal;
30770b57cec5SDimitry Andric         if (!E->evaluateAsAbsolute(ScaleVal, getStreamer().getAssemblerPtr()))
3078e8d8bef9SDimitry Andric           return Error(Loc, "expected absolute expression");
30790b57cec5SDimitry Andric         if (ScaleVal != 1)
30800b57cec5SDimitry Andric           Warning(Loc, "scale factor without index register is ignored");
30810b57cec5SDimitry Andric         Scale = 1;
30820b57cec5SDimitry Andric       } else { // IndexReg Found.
30830b57cec5SDimitry Andric         IndexReg = cast<X86MCExpr>(E)->getRegNo();
30840b57cec5SDimitry Andric 
30850b57cec5SDimitry Andric         if (BaseReg == X86::RIP)
3086e8d8bef9SDimitry Andric           return Error(Loc,
3087e8d8bef9SDimitry Andric                        "%rip as base register can not have an index register");
30880b57cec5SDimitry Andric         if (IndexReg == X86::RIP)
3089e8d8bef9SDimitry Andric           return Error(Loc, "%rip is not allowed as an index register");
30900b57cec5SDimitry Andric 
30910b57cec5SDimitry Andric         if (parseOptionalToken(AsmToken::Comma)) {
30920b57cec5SDimitry Andric           // Parse the scale amount:
30930b57cec5SDimitry Andric           //  ::= ',' [scale-expression]
30940b57cec5SDimitry Andric 
30950b57cec5SDimitry Andric           // A scale amount without an index is ignored.
30960b57cec5SDimitry Andric           if (getLexer().isNot(AsmToken::RParen)) {
30970b57cec5SDimitry Andric             int64_t ScaleVal;
30980b57cec5SDimitry Andric             if (Parser.parseTokenLoc(Loc) ||
30990b57cec5SDimitry Andric                 Parser.parseAbsoluteExpression(ScaleVal))
3100e8d8bef9SDimitry Andric               return Error(Loc, "expected scale expression");
31010b57cec5SDimitry Andric             Scale = (unsigned)ScaleVal;
31020b57cec5SDimitry Andric             // Validate the scale amount.
31030b57cec5SDimitry Andric             if (X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg) &&
31040b57cec5SDimitry Andric                 Scale != 1)
3105e8d8bef9SDimitry Andric               return Error(Loc, "scale factor in 16-bit address must be 1");
31060b57cec5SDimitry Andric             if (checkScale(Scale, ErrMsg))
3107e8d8bef9SDimitry Andric               return Error(Loc, ErrMsg);
31080b57cec5SDimitry Andric           }
31090b57cec5SDimitry Andric         }
31100b57cec5SDimitry Andric       }
31110b57cec5SDimitry Andric     }
31120b57cec5SDimitry Andric   }
31130b57cec5SDimitry Andric 
31140b57cec5SDimitry Andric   // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
31150b57cec5SDimitry Andric   if (parseToken(AsmToken::RParen, "unexpected token in memory operand"))
3116e8d8bef9SDimitry Andric     return true;
31170b57cec5SDimitry Andric 
31180b57cec5SDimitry Andric   // This is to support otherwise illegal operand (%dx) found in various
31190b57cec5SDimitry Andric   // unofficial manuals examples (e.g. "out[s]?[bwl]? %al, (%dx)") and must now
31200b57cec5SDimitry Andric   // be supported. Mark such DX variants separately fix only in special cases.
31210b57cec5SDimitry Andric   if (BaseReg == X86::DX && IndexReg == 0 && Scale == 1 && SegReg == 0 &&
3122e8d8bef9SDimitry Andric       isa<MCConstantExpr>(Disp) &&
3123e8d8bef9SDimitry Andric       cast<MCConstantExpr>(Disp)->getValue() == 0) {
3124e8d8bef9SDimitry Andric     Operands.push_back(X86Operand::CreateDXReg(BaseLoc, BaseLoc));
3125e8d8bef9SDimitry Andric     return false;
3126e8d8bef9SDimitry Andric   }
31270b57cec5SDimitry Andric 
31280b57cec5SDimitry Andric   if (CheckBaseRegAndIndexRegAndScale(BaseReg, IndexReg, Scale, is64BitMode(),
31290b57cec5SDimitry Andric                                       ErrMsg))
3130e8d8bef9SDimitry Andric     return Error(BaseLoc, ErrMsg);
31310b57cec5SDimitry Andric 
3132cb14a3feSDimitry Andric   // If the displacement is a constant, check overflows. For 64-bit addressing,
3133cb14a3feSDimitry Andric   // gas requires isInt<32> and otherwise reports an error. For others, gas
3134cb14a3feSDimitry Andric   // reports a warning and allows a wider range. E.g. gas allows
3135cb14a3feSDimitry Andric   // [-0xffffffff,0xffffffff] for 32-bit addressing (e.g. Linux kernel uses
3136cb14a3feSDimitry Andric   // `leal -__PAGE_OFFSET(%ecx),%esp` where __PAGE_OFFSET is 0xc0000000).
3137cb14a3feSDimitry Andric   if (BaseReg || IndexReg) {
3138cb14a3feSDimitry Andric     if (auto CE = dyn_cast<MCConstantExpr>(Disp)) {
3139cb14a3feSDimitry Andric       auto Imm = CE->getValue();
3140cb14a3feSDimitry Andric       bool Is64 = X86MCRegisterClasses[X86::GR64RegClassID].contains(BaseReg) ||
3141cb14a3feSDimitry Andric                   X86MCRegisterClasses[X86::GR64RegClassID].contains(IndexReg);
3142cb14a3feSDimitry Andric       bool Is16 = X86MCRegisterClasses[X86::GR16RegClassID].contains(BaseReg);
3143cb14a3feSDimitry Andric       if (Is64) {
3144cb14a3feSDimitry Andric         if (!isInt<32>(Imm))
3145cb14a3feSDimitry Andric           return Error(BaseLoc, "displacement " + Twine(Imm) +
3146cb14a3feSDimitry Andric                                     " is not within [-2147483648, 2147483647]");
3147cb14a3feSDimitry Andric       } else if (!Is16) {
3148cb14a3feSDimitry Andric         if (!isUInt<32>(Imm < 0 ? -uint64_t(Imm) : uint64_t(Imm))) {
3149cb14a3feSDimitry Andric           Warning(BaseLoc, "displacement " + Twine(Imm) +
3150cb14a3feSDimitry Andric                                " shortened to 32-bit signed " +
3151cb14a3feSDimitry Andric                                Twine(static_cast<int32_t>(Imm)));
3152cb14a3feSDimitry Andric         }
3153cb14a3feSDimitry Andric       } else if (!isUInt<16>(Imm < 0 ? -uint64_t(Imm) : uint64_t(Imm))) {
3154cb14a3feSDimitry Andric         Warning(BaseLoc, "displacement " + Twine(Imm) +
3155cb14a3feSDimitry Andric                              " shortened to 16-bit signed " +
3156cb14a3feSDimitry Andric                              Twine(static_cast<int16_t>(Imm)));
3157cb14a3feSDimitry Andric       }
3158cb14a3feSDimitry Andric     }
3159cb14a3feSDimitry Andric   }
3160cb14a3feSDimitry Andric 
31610b57cec5SDimitry Andric   if (SegReg || BaseReg || IndexReg)
3162e8d8bef9SDimitry Andric     Operands.push_back(X86Operand::CreateMem(getPointerWidth(), SegReg, Disp,
3163e8d8bef9SDimitry Andric                                              BaseReg, IndexReg, Scale, StartLoc,
3164e8d8bef9SDimitry Andric                                              EndLoc));
3165e8d8bef9SDimitry Andric   else
3166e8d8bef9SDimitry Andric     Operands.push_back(
3167e8d8bef9SDimitry Andric         X86Operand::CreateMem(getPointerWidth(), Disp, StartLoc, EndLoc));
3168e8d8bef9SDimitry Andric   return false;
31690b57cec5SDimitry Andric }
31700b57cec5SDimitry Andric 
31710b57cec5SDimitry Andric // Parse either a standard primary expression or a register.
parsePrimaryExpr(const MCExpr * & Res,SMLoc & EndLoc)31720b57cec5SDimitry Andric bool X86AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
31730b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
31740b57cec5SDimitry Andric   // See if this is a register first.
31750b57cec5SDimitry Andric   if (getTok().is(AsmToken::Percent) ||
31760b57cec5SDimitry Andric       (isParsingIntelSyntax() && getTok().is(AsmToken::Identifier) &&
31770b57cec5SDimitry Andric        MatchRegisterName(Parser.getTok().getString()))) {
31780b57cec5SDimitry Andric     SMLoc StartLoc = Parser.getTok().getLoc();
3179bdd1243dSDimitry Andric     MCRegister RegNo;
3180bdd1243dSDimitry Andric     if (parseRegister(RegNo, StartLoc, EndLoc))
31810b57cec5SDimitry Andric       return true;
31820b57cec5SDimitry Andric     Res = X86MCExpr::create(RegNo, Parser.getContext());
31830b57cec5SDimitry Andric     return false;
31840b57cec5SDimitry Andric   }
3185e8d8bef9SDimitry Andric   return Parser.parsePrimaryExpr(Res, EndLoc, nullptr);
31860b57cec5SDimitry Andric }
31870b57cec5SDimitry Andric 
ParseInstruction(ParseInstructionInfo & Info,StringRef Name,SMLoc NameLoc,OperandVector & Operands)31880b57cec5SDimitry Andric bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
31890b57cec5SDimitry Andric                                     SMLoc NameLoc, OperandVector &Operands) {
31900b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
31910b57cec5SDimitry Andric   InstInfo = &Info;
31920b57cec5SDimitry Andric 
31930b57cec5SDimitry Andric   // Reset the forced VEX encoding.
31940fca6ea1SDimitry Andric   ForcedOpcodePrefix = OpcodePrefix_Default;
3195e8d8bef9SDimitry Andric   ForcedDispEncoding = DispEncoding_Default;
31965f757f3fSDimitry Andric   UseApxExtendedReg = false;
3197647cbc5dSDimitry Andric   ForcedNoFlag = false;
31980b57cec5SDimitry Andric 
31990b57cec5SDimitry Andric   // Parse pseudo prefixes.
320004eeddc0SDimitry Andric   while (true) {
32010b57cec5SDimitry Andric     if (Name == "{") {
32020b57cec5SDimitry Andric       if (getLexer().isNot(AsmToken::Identifier))
32030b57cec5SDimitry Andric         return Error(Parser.getTok().getLoc(), "Unexpected token after '{'");
32040b57cec5SDimitry Andric       std::string Prefix = Parser.getTok().getString().lower();
32050b57cec5SDimitry Andric       Parser.Lex(); // Eat identifier.
32060b57cec5SDimitry Andric       if (getLexer().isNot(AsmToken::RCurly))
32070b57cec5SDimitry Andric         return Error(Parser.getTok().getLoc(), "Expected '}'");
32080b57cec5SDimitry Andric       Parser.Lex(); // Eat curly.
32090b57cec5SDimitry Andric 
32100fca6ea1SDimitry Andric       if (Prefix == "rex")
32110fca6ea1SDimitry Andric         ForcedOpcodePrefix = OpcodePrefix_REX;
32120fca6ea1SDimitry Andric       else if (Prefix == "rex2")
32130fca6ea1SDimitry Andric         ForcedOpcodePrefix = OpcodePrefix_REX2;
32140fca6ea1SDimitry Andric       else if (Prefix == "vex")
32150fca6ea1SDimitry Andric         ForcedOpcodePrefix = OpcodePrefix_VEX;
3216e8d8bef9SDimitry Andric       else if (Prefix == "vex2")
32170fca6ea1SDimitry Andric         ForcedOpcodePrefix = OpcodePrefix_VEX2;
32180b57cec5SDimitry Andric       else if (Prefix == "vex3")
32190fca6ea1SDimitry Andric         ForcedOpcodePrefix = OpcodePrefix_VEX3;
32200b57cec5SDimitry Andric       else if (Prefix == "evex")
32210fca6ea1SDimitry Andric         ForcedOpcodePrefix = OpcodePrefix_EVEX;
3222e8d8bef9SDimitry Andric       else if (Prefix == "disp8")
3223e8d8bef9SDimitry Andric         ForcedDispEncoding = DispEncoding_Disp8;
3224e8d8bef9SDimitry Andric       else if (Prefix == "disp32")
3225e8d8bef9SDimitry Andric         ForcedDispEncoding = DispEncoding_Disp32;
3226647cbc5dSDimitry Andric       else if (Prefix == "nf")
3227647cbc5dSDimitry Andric         ForcedNoFlag = true;
32280b57cec5SDimitry Andric       else
32290b57cec5SDimitry Andric         return Error(NameLoc, "unknown prefix");
32300b57cec5SDimitry Andric 
32310b57cec5SDimitry Andric       NameLoc = Parser.getTok().getLoc();
32320b57cec5SDimitry Andric       if (getLexer().is(AsmToken::LCurly)) {
32330b57cec5SDimitry Andric         Parser.Lex();
32340b57cec5SDimitry Andric         Name = "{";
32350b57cec5SDimitry Andric       } else {
32360b57cec5SDimitry Andric         if (getLexer().isNot(AsmToken::Identifier))
32370b57cec5SDimitry Andric           return Error(Parser.getTok().getLoc(), "Expected identifier");
32380b57cec5SDimitry Andric         // FIXME: The mnemonic won't match correctly if its not in lower case.
32390b57cec5SDimitry Andric         Name = Parser.getTok().getString();
32400b57cec5SDimitry Andric         Parser.Lex();
32410b57cec5SDimitry Andric       }
32420b57cec5SDimitry Andric       continue;
32430b57cec5SDimitry Andric     }
3244e8d8bef9SDimitry Andric     // Parse MASM style pseudo prefixes.
3245e8d8bef9SDimitry Andric     if (isParsingMSInlineAsm()) {
3246fe6060f1SDimitry Andric       if (Name.equals_insensitive("vex"))
32470fca6ea1SDimitry Andric         ForcedOpcodePrefix = OpcodePrefix_VEX;
3248fe6060f1SDimitry Andric       else if (Name.equals_insensitive("vex2"))
32490fca6ea1SDimitry Andric         ForcedOpcodePrefix = OpcodePrefix_VEX2;
3250fe6060f1SDimitry Andric       else if (Name.equals_insensitive("vex3"))
32510fca6ea1SDimitry Andric         ForcedOpcodePrefix = OpcodePrefix_VEX3;
3252fe6060f1SDimitry Andric       else if (Name.equals_insensitive("evex"))
32530fca6ea1SDimitry Andric         ForcedOpcodePrefix = OpcodePrefix_EVEX;
32540b57cec5SDimitry Andric 
32550fca6ea1SDimitry Andric       if (ForcedOpcodePrefix != OpcodePrefix_Default) {
3256e8d8bef9SDimitry Andric         if (getLexer().isNot(AsmToken::Identifier))
3257e8d8bef9SDimitry Andric           return Error(Parser.getTok().getLoc(), "Expected identifier");
3258e8d8bef9SDimitry Andric         // FIXME: The mnemonic won't match correctly if its not in lower case.
3259e8d8bef9SDimitry Andric         Name = Parser.getTok().getString();
3260e8d8bef9SDimitry Andric         NameLoc = Parser.getTok().getLoc();
3261e8d8bef9SDimitry Andric         Parser.Lex();
3262e8d8bef9SDimitry Andric       }
3263e8d8bef9SDimitry Andric     }
32640b57cec5SDimitry Andric     break;
32650b57cec5SDimitry Andric   }
32660b57cec5SDimitry Andric 
3267e8d8bef9SDimitry Andric   // Support the suffix syntax for overriding displacement size as well.
3268e8d8bef9SDimitry Andric   if (Name.consume_back(".d32")) {
3269e8d8bef9SDimitry Andric     ForcedDispEncoding = DispEncoding_Disp32;
3270e8d8bef9SDimitry Andric   } else if (Name.consume_back(".d8")) {
3271e8d8bef9SDimitry Andric     ForcedDispEncoding = DispEncoding_Disp8;
3272e8d8bef9SDimitry Andric   }
3273e8d8bef9SDimitry Andric 
32740b57cec5SDimitry Andric   StringRef PatchedName = Name;
32750b57cec5SDimitry Andric 
32760b57cec5SDimitry Andric   // Hack to skip "short" following Jcc.
32770b57cec5SDimitry Andric   if (isParsingIntelSyntax() &&
32780b57cec5SDimitry Andric       (PatchedName == "jmp" || PatchedName == "jc" || PatchedName == "jnc" ||
3279fe6060f1SDimitry Andric        PatchedName == "jcxz" || PatchedName == "jecxz" ||
32805f757f3fSDimitry Andric        (PatchedName.starts_with("j") &&
32810b57cec5SDimitry Andric         ParseConditionCode(PatchedName.substr(1)) != X86::COND_INVALID))) {
32820b57cec5SDimitry Andric     StringRef NextTok = Parser.getTok().getString();
3283fe6060f1SDimitry Andric     if (Parser.isParsingMasm() ? NextTok.equals_insensitive("short")
3284fe6060f1SDimitry Andric                                : NextTok == "short") {
32850b57cec5SDimitry Andric       SMLoc NameEndLoc =
32860b57cec5SDimitry Andric           NameLoc.getFromPointer(NameLoc.getPointer() + Name.size());
32870b57cec5SDimitry Andric       // Eat the short keyword.
32880b57cec5SDimitry Andric       Parser.Lex();
32890b57cec5SDimitry Andric       // MS and GAS ignore the short keyword; they both determine the jmp type
32900b57cec5SDimitry Andric       // based on the distance of the label. (NASM does emit different code with
32910b57cec5SDimitry Andric       // and without "short," though.)
32920b57cec5SDimitry Andric       InstInfo->AsmRewrites->emplace_back(AOK_Skip, NameEndLoc,
32930b57cec5SDimitry Andric                                           NextTok.size() + 1);
32940b57cec5SDimitry Andric     }
32950b57cec5SDimitry Andric   }
32960b57cec5SDimitry Andric 
32970b57cec5SDimitry Andric   // FIXME: Hack to recognize setneb as setne.
32985f757f3fSDimitry Andric   if (PatchedName.starts_with("set") && PatchedName.ends_with("b") &&
32990fca6ea1SDimitry Andric       PatchedName != "setzub" && PatchedName != "setzunb" &&
33000b57cec5SDimitry Andric       PatchedName != "setb" && PatchedName != "setnb")
33010b57cec5SDimitry Andric     PatchedName = PatchedName.substr(0, Name.size()-1);
33020b57cec5SDimitry Andric 
33030b57cec5SDimitry Andric   unsigned ComparisonPredicate = ~0U;
33040b57cec5SDimitry Andric 
3305349cc55cSDimitry Andric   // FIXME: Hack to recognize cmp<comparison code>{sh,ss,sd,ph,ps,pd}.
33065f757f3fSDimitry Andric   if ((PatchedName.starts_with("cmp") || PatchedName.starts_with("vcmp")) &&
33075f757f3fSDimitry Andric       (PatchedName.ends_with("ss") || PatchedName.ends_with("sd") ||
33085f757f3fSDimitry Andric        PatchedName.ends_with("sh") || PatchedName.ends_with("ph") ||
33095f757f3fSDimitry Andric        PatchedName.ends_with("ps") || PatchedName.ends_with("pd"))) {
33100b57cec5SDimitry Andric     bool IsVCMP = PatchedName[0] == 'v';
33110b57cec5SDimitry Andric     unsigned CCIdx = IsVCMP ? 4 : 3;
33120b57cec5SDimitry Andric     unsigned CC = StringSwitch<unsigned>(
33130b57cec5SDimitry Andric       PatchedName.slice(CCIdx, PatchedName.size() - 2))
33140b57cec5SDimitry Andric       .Case("eq",       0x00)
33150b57cec5SDimitry Andric       .Case("eq_oq",    0x00)
33160b57cec5SDimitry Andric       .Case("lt",       0x01)
33170b57cec5SDimitry Andric       .Case("lt_os",    0x01)
33180b57cec5SDimitry Andric       .Case("le",       0x02)
33190b57cec5SDimitry Andric       .Case("le_os",    0x02)
33200b57cec5SDimitry Andric       .Case("unord",    0x03)
33210b57cec5SDimitry Andric       .Case("unord_q",  0x03)
33220b57cec5SDimitry Andric       .Case("neq",      0x04)
33230b57cec5SDimitry Andric       .Case("neq_uq",   0x04)
33240b57cec5SDimitry Andric       .Case("nlt",      0x05)
33250b57cec5SDimitry Andric       .Case("nlt_us",   0x05)
33260b57cec5SDimitry Andric       .Case("nle",      0x06)
33270b57cec5SDimitry Andric       .Case("nle_us",   0x06)
33280b57cec5SDimitry Andric       .Case("ord",      0x07)
33290b57cec5SDimitry Andric       .Case("ord_q",    0x07)
33300b57cec5SDimitry Andric       /* AVX only from here */
33310b57cec5SDimitry Andric       .Case("eq_uq",    0x08)
33320b57cec5SDimitry Andric       .Case("nge",      0x09)
33330b57cec5SDimitry Andric       .Case("nge_us",   0x09)
33340b57cec5SDimitry Andric       .Case("ngt",      0x0A)
33350b57cec5SDimitry Andric       .Case("ngt_us",   0x0A)
33360b57cec5SDimitry Andric       .Case("false",    0x0B)
33370b57cec5SDimitry Andric       .Case("false_oq", 0x0B)
33380b57cec5SDimitry Andric       .Case("neq_oq",   0x0C)
33390b57cec5SDimitry Andric       .Case("ge",       0x0D)
33400b57cec5SDimitry Andric       .Case("ge_os",    0x0D)
33410b57cec5SDimitry Andric       .Case("gt",       0x0E)
33420b57cec5SDimitry Andric       .Case("gt_os",    0x0E)
33430b57cec5SDimitry Andric       .Case("true",     0x0F)
33440b57cec5SDimitry Andric       .Case("true_uq",  0x0F)
33450b57cec5SDimitry Andric       .Case("eq_os",    0x10)
33460b57cec5SDimitry Andric       .Case("lt_oq",    0x11)
33470b57cec5SDimitry Andric       .Case("le_oq",    0x12)
33480b57cec5SDimitry Andric       .Case("unord_s",  0x13)
33490b57cec5SDimitry Andric       .Case("neq_us",   0x14)
33500b57cec5SDimitry Andric       .Case("nlt_uq",   0x15)
33510b57cec5SDimitry Andric       .Case("nle_uq",   0x16)
33520b57cec5SDimitry Andric       .Case("ord_s",    0x17)
33530b57cec5SDimitry Andric       .Case("eq_us",    0x18)
33540b57cec5SDimitry Andric       .Case("nge_uq",   0x19)
33550b57cec5SDimitry Andric       .Case("ngt_uq",   0x1A)
33560b57cec5SDimitry Andric       .Case("false_os", 0x1B)
33570b57cec5SDimitry Andric       .Case("neq_os",   0x1C)
33580b57cec5SDimitry Andric       .Case("ge_oq",    0x1D)
33590b57cec5SDimitry Andric       .Case("gt_oq",    0x1E)
33600b57cec5SDimitry Andric       .Case("true_us",  0x1F)
33610b57cec5SDimitry Andric       .Default(~0U);
3362349cc55cSDimitry Andric     if (CC != ~0U && (IsVCMP || CC < 8) &&
3363349cc55cSDimitry Andric         (IsVCMP || PatchedName.back() != 'h')) {
33645f757f3fSDimitry Andric       if (PatchedName.ends_with("ss"))
33650b57cec5SDimitry Andric         PatchedName = IsVCMP ? "vcmpss" : "cmpss";
33665f757f3fSDimitry Andric       else if (PatchedName.ends_with("sd"))
33670b57cec5SDimitry Andric         PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
33685f757f3fSDimitry Andric       else if (PatchedName.ends_with("ps"))
33690b57cec5SDimitry Andric         PatchedName = IsVCMP ? "vcmpps" : "cmpps";
33705f757f3fSDimitry Andric       else if (PatchedName.ends_with("pd"))
33710b57cec5SDimitry Andric         PatchedName = IsVCMP ? "vcmppd" : "cmppd";
33725f757f3fSDimitry Andric       else if (PatchedName.ends_with("sh"))
3373349cc55cSDimitry Andric         PatchedName = "vcmpsh";
33745f757f3fSDimitry Andric       else if (PatchedName.ends_with("ph"))
3375349cc55cSDimitry Andric         PatchedName = "vcmpph";
33760b57cec5SDimitry Andric       else
33770b57cec5SDimitry Andric         llvm_unreachable("Unexpected suffix!");
33780b57cec5SDimitry Andric 
33790b57cec5SDimitry Andric       ComparisonPredicate = CC;
33800b57cec5SDimitry Andric     }
33810b57cec5SDimitry Andric   }
33820b57cec5SDimitry Andric 
33830b57cec5SDimitry Andric   // FIXME: Hack to recognize vpcmp<comparison code>{ub,uw,ud,uq,b,w,d,q}.
33845f757f3fSDimitry Andric   if (PatchedName.starts_with("vpcmp") &&
33850b57cec5SDimitry Andric       (PatchedName.back() == 'b' || PatchedName.back() == 'w' ||
33860b57cec5SDimitry Andric        PatchedName.back() == 'd' || PatchedName.back() == 'q')) {
33870b57cec5SDimitry Andric     unsigned SuffixSize = PatchedName.drop_back().back() == 'u' ? 2 : 1;
33880b57cec5SDimitry Andric     unsigned CC = StringSwitch<unsigned>(
33890b57cec5SDimitry Andric       PatchedName.slice(5, PatchedName.size() - SuffixSize))
33900b57cec5SDimitry Andric       .Case("eq",    0x0) // Only allowed on unsigned. Checked below.
33910b57cec5SDimitry Andric       .Case("lt",    0x1)
33920b57cec5SDimitry Andric       .Case("le",    0x2)
33930b57cec5SDimitry Andric       //.Case("false", 0x3) // Not a documented alias.
33940b57cec5SDimitry Andric       .Case("neq",   0x4)
33950b57cec5SDimitry Andric       .Case("nlt",   0x5)
33960b57cec5SDimitry Andric       .Case("nle",   0x6)
33970b57cec5SDimitry Andric       //.Case("true",  0x7) // Not a documented alias.
33980b57cec5SDimitry Andric       .Default(~0U);
33990b57cec5SDimitry Andric     if (CC != ~0U && (CC != 0 || SuffixSize == 2)) {
34000b57cec5SDimitry Andric       switch (PatchedName.back()) {
34010b57cec5SDimitry Andric       default: llvm_unreachable("Unexpected character!");
34020b57cec5SDimitry Andric       case 'b': PatchedName = SuffixSize == 2 ? "vpcmpub" : "vpcmpb"; break;
34030b57cec5SDimitry Andric       case 'w': PatchedName = SuffixSize == 2 ? "vpcmpuw" : "vpcmpw"; break;
34040b57cec5SDimitry Andric       case 'd': PatchedName = SuffixSize == 2 ? "vpcmpud" : "vpcmpd"; break;
34050b57cec5SDimitry Andric       case 'q': PatchedName = SuffixSize == 2 ? "vpcmpuq" : "vpcmpq"; break;
34060b57cec5SDimitry Andric       }
34070b57cec5SDimitry Andric       // Set up the immediate to push into the operands later.
34080b57cec5SDimitry Andric       ComparisonPredicate = CC;
34090b57cec5SDimitry Andric     }
34100b57cec5SDimitry Andric   }
34110b57cec5SDimitry Andric 
34120b57cec5SDimitry Andric   // FIXME: Hack to recognize vpcom<comparison code>{ub,uw,ud,uq,b,w,d,q}.
34135f757f3fSDimitry Andric   if (PatchedName.starts_with("vpcom") &&
34140b57cec5SDimitry Andric       (PatchedName.back() == 'b' || PatchedName.back() == 'w' ||
34150b57cec5SDimitry Andric        PatchedName.back() == 'd' || PatchedName.back() == 'q')) {
34160b57cec5SDimitry Andric     unsigned SuffixSize = PatchedName.drop_back().back() == 'u' ? 2 : 1;
34170b57cec5SDimitry Andric     unsigned CC = StringSwitch<unsigned>(
34180b57cec5SDimitry Andric       PatchedName.slice(5, PatchedName.size() - SuffixSize))
34190b57cec5SDimitry Andric       .Case("lt",    0x0)
34200b57cec5SDimitry Andric       .Case("le",    0x1)
34210b57cec5SDimitry Andric       .Case("gt",    0x2)
34220b57cec5SDimitry Andric       .Case("ge",    0x3)
34230b57cec5SDimitry Andric       .Case("eq",    0x4)
34240b57cec5SDimitry Andric       .Case("neq",   0x5)
34250b57cec5SDimitry Andric       .Case("false", 0x6)
34260b57cec5SDimitry Andric       .Case("true",  0x7)
34270b57cec5SDimitry Andric       .Default(~0U);
34280b57cec5SDimitry Andric     if (CC != ~0U) {
34290b57cec5SDimitry Andric       switch (PatchedName.back()) {
34300b57cec5SDimitry Andric       default: llvm_unreachable("Unexpected character!");
34310b57cec5SDimitry Andric       case 'b': PatchedName = SuffixSize == 2 ? "vpcomub" : "vpcomb"; break;
34320b57cec5SDimitry Andric       case 'w': PatchedName = SuffixSize == 2 ? "vpcomuw" : "vpcomw"; break;
34330b57cec5SDimitry Andric       case 'd': PatchedName = SuffixSize == 2 ? "vpcomud" : "vpcomd"; break;
34340b57cec5SDimitry Andric       case 'q': PatchedName = SuffixSize == 2 ? "vpcomuq" : "vpcomq"; break;
34350b57cec5SDimitry Andric       }
34360b57cec5SDimitry Andric       // Set up the immediate to push into the operands later.
34370b57cec5SDimitry Andric       ComparisonPredicate = CC;
34380b57cec5SDimitry Andric     }
34390b57cec5SDimitry Andric   }
34400b57cec5SDimitry Andric 
34410b57cec5SDimitry Andric   // Determine whether this is an instruction prefix.
34420b57cec5SDimitry Andric   // FIXME:
34430b57cec5SDimitry Andric   // Enhance prefixes integrity robustness. for example, following forms
34440b57cec5SDimitry Andric   // are currently tolerated:
34450b57cec5SDimitry Andric   // repz repnz <insn>    ; GAS errors for the use of two similar prefixes
34460b57cec5SDimitry Andric   // lock addq %rax, %rbx ; Destination operand must be of memory type
34470b57cec5SDimitry Andric   // xacquire <insn>      ; xacquire must be accompanied by 'lock'
3448e8d8bef9SDimitry Andric   bool IsPrefix =
3449e8d8bef9SDimitry Andric       StringSwitch<bool>(Name)
3450e8d8bef9SDimitry Andric           .Cases("cs", "ds", "es", "fs", "gs", "ss", true)
3451e8d8bef9SDimitry Andric           .Cases("rex64", "data32", "data16", "addr32", "addr16", true)
34520b57cec5SDimitry Andric           .Cases("xacquire", "xrelease", true)
34530b57cec5SDimitry Andric           .Cases("acquire", "release", isParsingIntelSyntax())
34540b57cec5SDimitry Andric           .Default(false);
34550b57cec5SDimitry Andric 
34560b57cec5SDimitry Andric   auto isLockRepeatNtPrefix = [](StringRef N) {
34570b57cec5SDimitry Andric     return StringSwitch<bool>(N)
34580b57cec5SDimitry Andric         .Cases("lock", "rep", "repe", "repz", "repne", "repnz", "notrack", true)
34590b57cec5SDimitry Andric         .Default(false);
34600b57cec5SDimitry Andric   };
34610b57cec5SDimitry Andric 
34620b57cec5SDimitry Andric   bool CurlyAsEndOfStatement = false;
34630b57cec5SDimitry Andric 
34640b57cec5SDimitry Andric   unsigned Flags = X86::IP_NO_PREFIX;
34650b57cec5SDimitry Andric   while (isLockRepeatNtPrefix(Name.lower())) {
34660b57cec5SDimitry Andric     unsigned Prefix =
34670b57cec5SDimitry Andric         StringSwitch<unsigned>(Name)
34680b57cec5SDimitry Andric             .Cases("lock", "lock", X86::IP_HAS_LOCK)
34690b57cec5SDimitry Andric             .Cases("rep", "repe", "repz", X86::IP_HAS_REPEAT)
34700b57cec5SDimitry Andric             .Cases("repne", "repnz", X86::IP_HAS_REPEAT_NE)
34710b57cec5SDimitry Andric             .Cases("notrack", "notrack", X86::IP_HAS_NOTRACK)
34720b57cec5SDimitry Andric             .Default(X86::IP_NO_PREFIX); // Invalid prefix (impossible)
34730b57cec5SDimitry Andric     Flags |= Prefix;
34740b57cec5SDimitry Andric     if (getLexer().is(AsmToken::EndOfStatement)) {
34750b57cec5SDimitry Andric       // We don't have real instr with the given prefix
34760b57cec5SDimitry Andric       //  let's use the prefix as the instr.
34770b57cec5SDimitry Andric       // TODO: there could be several prefixes one after another
34780b57cec5SDimitry Andric       Flags = X86::IP_NO_PREFIX;
34790b57cec5SDimitry Andric       break;
34800b57cec5SDimitry Andric     }
34810b57cec5SDimitry Andric     // FIXME: The mnemonic won't match correctly if its not in lower case.
34820b57cec5SDimitry Andric     Name = Parser.getTok().getString();
34830b57cec5SDimitry Andric     Parser.Lex(); // eat the prefix
34840b57cec5SDimitry Andric     // Hack: we could have something like "rep # some comment" or
34850b57cec5SDimitry Andric     //    "lock; cmpxchg16b $1" or "lock\0A\09incl" or "lock/incl"
34865f757f3fSDimitry Andric     while (Name.starts_with(";") || Name.starts_with("\n") ||
34875f757f3fSDimitry Andric            Name.starts_with("#") || Name.starts_with("\t") ||
34885f757f3fSDimitry Andric            Name.starts_with("/")) {
34890b57cec5SDimitry Andric       // FIXME: The mnemonic won't match correctly if its not in lower case.
34900b57cec5SDimitry Andric       Name = Parser.getTok().getString();
34910b57cec5SDimitry Andric       Parser.Lex(); // go to next prefix or instr
34920b57cec5SDimitry Andric     }
34930b57cec5SDimitry Andric   }
34940b57cec5SDimitry Andric 
34950b57cec5SDimitry Andric   if (Flags)
34960b57cec5SDimitry Andric     PatchedName = Name;
34970b57cec5SDimitry Andric 
34980b57cec5SDimitry Andric   // Hacks to handle 'data16' and 'data32'
34990b57cec5SDimitry Andric   if (PatchedName == "data16" && is16BitMode()) {
35000b57cec5SDimitry Andric     return Error(NameLoc, "redundant data16 prefix");
35010b57cec5SDimitry Andric   }
35020b57cec5SDimitry Andric   if (PatchedName == "data32") {
35030b57cec5SDimitry Andric     if (is32BitMode())
35040b57cec5SDimitry Andric       return Error(NameLoc, "redundant data32 prefix");
35050b57cec5SDimitry Andric     if (is64BitMode())
35060b57cec5SDimitry Andric       return Error(NameLoc, "'data32' is not supported in 64-bit mode");
35070b57cec5SDimitry Andric     // Hack to 'data16' for the table lookup.
35080b57cec5SDimitry Andric     PatchedName = "data16";
3509e8d8bef9SDimitry Andric 
3510e8d8bef9SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
3511e8d8bef9SDimitry Andric       StringRef Next = Parser.getTok().getString();
3512e8d8bef9SDimitry Andric       getLexer().Lex();
3513e8d8bef9SDimitry Andric       // data32 effectively changes the instruction suffix.
3514e8d8bef9SDimitry Andric       // TODO Generalize.
3515e8d8bef9SDimitry Andric       if (Next == "callw")
3516e8d8bef9SDimitry Andric         Next = "calll";
3517e8d8bef9SDimitry Andric       if (Next == "ljmpw")
3518e8d8bef9SDimitry Andric         Next = "ljmpl";
3519e8d8bef9SDimitry Andric 
3520e8d8bef9SDimitry Andric       Name = Next;
3521e8d8bef9SDimitry Andric       PatchedName = Name;
352281ad6265SDimitry Andric       ForcedDataPrefix = X86::Is32Bit;
3523e8d8bef9SDimitry Andric       IsPrefix = false;
3524e8d8bef9SDimitry Andric     }
35250b57cec5SDimitry Andric   }
35260b57cec5SDimitry Andric 
35270b57cec5SDimitry Andric   Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
35280b57cec5SDimitry Andric 
35290b57cec5SDimitry Andric   // Push the immediate if we extracted one from the mnemonic.
35300b57cec5SDimitry Andric   if (ComparisonPredicate != ~0U && !isParsingIntelSyntax()) {
35310b57cec5SDimitry Andric     const MCExpr *ImmOp = MCConstantExpr::create(ComparisonPredicate,
35320b57cec5SDimitry Andric                                                  getParser().getContext());
35330b57cec5SDimitry Andric     Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));
35340b57cec5SDimitry Andric   }
35350b57cec5SDimitry Andric 
35360fca6ea1SDimitry Andric   // Parse condtional flags after mnemonic.
35370fca6ea1SDimitry Andric   if ((Name.starts_with("ccmp") || Name.starts_with("ctest")) &&
35380fca6ea1SDimitry Andric       parseCFlagsOp(Operands))
35390fca6ea1SDimitry Andric     return true;
35400fca6ea1SDimitry Andric 
35410b57cec5SDimitry Andric   // This does the actual operand parsing.  Don't parse any more if we have a
35420b57cec5SDimitry Andric   // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we
35430b57cec5SDimitry Andric   // just want to parse the "lock" as the first instruction and the "incl" as
35440b57cec5SDimitry Andric   // the next one.
3545e8d8bef9SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement) && !IsPrefix) {
35460b57cec5SDimitry Andric     // Parse '*' modifier.
35470b57cec5SDimitry Andric     if (getLexer().is(AsmToken::Star))
35480b57cec5SDimitry Andric       Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
35490b57cec5SDimitry Andric 
35500b57cec5SDimitry Andric     // Read the operands.
355104eeddc0SDimitry Andric     while (true) {
355281ad6265SDimitry Andric       if (parseOperand(Operands, Name))
35530b57cec5SDimitry Andric         return true;
3554e8d8bef9SDimitry Andric       if (HandleAVX512Operand(Operands))
35550b57cec5SDimitry Andric         return true;
3556e8d8bef9SDimitry Andric 
35570b57cec5SDimitry Andric       // check for comma and eat it
35580b57cec5SDimitry Andric       if (getLexer().is(AsmToken::Comma))
35590b57cec5SDimitry Andric         Parser.Lex();
35600b57cec5SDimitry Andric       else
35610b57cec5SDimitry Andric         break;
35620b57cec5SDimitry Andric      }
35630b57cec5SDimitry Andric 
35640b57cec5SDimitry Andric     // In MS inline asm curly braces mark the beginning/end of a block,
35650b57cec5SDimitry Andric     // therefore they should be interepreted as end of statement
35660b57cec5SDimitry Andric     CurlyAsEndOfStatement =
35675ffd83dbSDimitry Andric         isParsingIntelSyntax() && isParsingMSInlineAsm() &&
35680b57cec5SDimitry Andric         (getLexer().is(AsmToken::LCurly) || getLexer().is(AsmToken::RCurly));
35690b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement) && !CurlyAsEndOfStatement)
35700b57cec5SDimitry Andric       return TokError("unexpected token in argument list");
35710b57cec5SDimitry Andric   }
35720b57cec5SDimitry Andric 
35730b57cec5SDimitry Andric   // Push the immediate if we extracted one from the mnemonic.
35740b57cec5SDimitry Andric   if (ComparisonPredicate != ~0U && isParsingIntelSyntax()) {
35750b57cec5SDimitry Andric     const MCExpr *ImmOp = MCConstantExpr::create(ComparisonPredicate,
35760b57cec5SDimitry Andric                                                  getParser().getContext());
35770b57cec5SDimitry Andric     Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc));
35780b57cec5SDimitry Andric   }
35790b57cec5SDimitry Andric 
35800b57cec5SDimitry Andric   // Consume the EndOfStatement or the prefix separator Slash
35810b57cec5SDimitry Andric   if (getLexer().is(AsmToken::EndOfStatement) ||
3582e8d8bef9SDimitry Andric       (IsPrefix && getLexer().is(AsmToken::Slash)))
35830b57cec5SDimitry Andric     Parser.Lex();
35840b57cec5SDimitry Andric   else if (CurlyAsEndOfStatement)
35850b57cec5SDimitry Andric     // Add an actual EndOfStatement before the curly brace
35860b57cec5SDimitry Andric     Info.AsmRewrites->emplace_back(AOK_EndOfStatement,
35870b57cec5SDimitry Andric                                    getLexer().getTok().getLoc(), 0);
35880b57cec5SDimitry Andric 
35890b57cec5SDimitry Andric   // This is for gas compatibility and cannot be done in td.
35900b57cec5SDimitry Andric   // Adding "p" for some floating point with no argument.
35910b57cec5SDimitry Andric   // For example: fsub --> fsubp
35920b57cec5SDimitry Andric   bool IsFp =
35930b57cec5SDimitry Andric     Name == "fsub" || Name == "fdiv" || Name == "fsubr" || Name == "fdivr";
35940b57cec5SDimitry Andric   if (IsFp && Operands.size() == 1) {
35950b57cec5SDimitry Andric     const char *Repl = StringSwitch<const char *>(Name)
35960b57cec5SDimitry Andric       .Case("fsub", "fsubp")
35970b57cec5SDimitry Andric       .Case("fdiv", "fdivp")
35980b57cec5SDimitry Andric       .Case("fsubr", "fsubrp")
35990b57cec5SDimitry Andric       .Case("fdivr", "fdivrp");
36000b57cec5SDimitry Andric     static_cast<X86Operand &>(*Operands[0]).setTokenValue(Repl);
36010b57cec5SDimitry Andric   }
36020b57cec5SDimitry Andric 
36030b57cec5SDimitry Andric   if ((Name == "mov" || Name == "movw" || Name == "movl") &&
36040b57cec5SDimitry Andric       (Operands.size() == 3)) {
36050b57cec5SDimitry Andric     X86Operand &Op1 = (X86Operand &)*Operands[1];
36060b57cec5SDimitry Andric     X86Operand &Op2 = (X86Operand &)*Operands[2];
36070b57cec5SDimitry Andric     SMLoc Loc = Op1.getEndLoc();
36080b57cec5SDimitry Andric     // Moving a 32 or 16 bit value into a segment register has the same
36090b57cec5SDimitry Andric     // behavior. Modify such instructions to always take shorter form.
36100b57cec5SDimitry Andric     if (Op1.isReg() && Op2.isReg() &&
36110b57cec5SDimitry Andric         X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(
36120b57cec5SDimitry Andric             Op2.getReg()) &&
36130b57cec5SDimitry Andric         (X86MCRegisterClasses[X86::GR16RegClassID].contains(Op1.getReg()) ||
36140b57cec5SDimitry Andric          X86MCRegisterClasses[X86::GR32RegClassID].contains(Op1.getReg()))) {
36150b57cec5SDimitry Andric       // Change instruction name to match new instruction.
36160b57cec5SDimitry Andric       if (Name != "mov" && Name[3] == (is16BitMode() ? 'l' : 'w')) {
36170b57cec5SDimitry Andric         Name = is16BitMode() ? "movw" : "movl";
36180b57cec5SDimitry Andric         Operands[0] = X86Operand::CreateToken(Name, NameLoc);
36190b57cec5SDimitry Andric       }
36200b57cec5SDimitry Andric       // Select the correct equivalent 16-/32-bit source register.
362106c3fb27SDimitry Andric       MCRegister Reg =
362206c3fb27SDimitry Andric           getX86SubSuperRegister(Op1.getReg(), is16BitMode() ? 16 : 32);
36230b57cec5SDimitry Andric       Operands[1] = X86Operand::CreateReg(Reg, Loc, Loc);
36240b57cec5SDimitry Andric     }
36250b57cec5SDimitry Andric   }
36260b57cec5SDimitry Andric 
36270b57cec5SDimitry Andric   // This is a terrible hack to handle "out[s]?[bwl]? %al, (%dx)" ->
36280b57cec5SDimitry Andric   // "outb %al, %dx".  Out doesn't take a memory form, but this is a widely
36290b57cec5SDimitry Andric   // documented form in various unofficial manuals, so a lot of code uses it.
36300b57cec5SDimitry Andric   if ((Name == "outb" || Name == "outsb" || Name == "outw" || Name == "outsw" ||
36310b57cec5SDimitry Andric        Name == "outl" || Name == "outsl" || Name == "out" || Name == "outs") &&
36320b57cec5SDimitry Andric       Operands.size() == 3) {
36330b57cec5SDimitry Andric     X86Operand &Op = (X86Operand &)*Operands.back();
36340b57cec5SDimitry Andric     if (Op.isDXReg())
36350b57cec5SDimitry Andric       Operands.back() = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),
36360b57cec5SDimitry Andric                                               Op.getEndLoc());
36370b57cec5SDimitry Andric   }
36380b57cec5SDimitry Andric   // Same hack for "in[s]?[bwl]? (%dx), %al" -> "inb %dx, %al".
36390b57cec5SDimitry Andric   if ((Name == "inb" || Name == "insb" || Name == "inw" || Name == "insw" ||
36400b57cec5SDimitry Andric        Name == "inl" || Name == "insl" || Name == "in" || Name == "ins") &&
36410b57cec5SDimitry Andric       Operands.size() == 3) {
36420b57cec5SDimitry Andric     X86Operand &Op = (X86Operand &)*Operands[1];
36430b57cec5SDimitry Andric     if (Op.isDXReg())
36440b57cec5SDimitry Andric       Operands[1] = X86Operand::CreateReg(X86::DX, Op.getStartLoc(),
36450b57cec5SDimitry Andric                                           Op.getEndLoc());
36460b57cec5SDimitry Andric   }
36470b57cec5SDimitry Andric 
36480b57cec5SDimitry Andric   SmallVector<std::unique_ptr<MCParsedAsmOperand>, 2> TmpOperands;
36490b57cec5SDimitry Andric   bool HadVerifyError = false;
36500b57cec5SDimitry Andric 
36510b57cec5SDimitry Andric   // Append default arguments to "ins[bwld]"
36525f757f3fSDimitry Andric   if (Name.starts_with("ins") &&
36530b57cec5SDimitry Andric       (Operands.size() == 1 || Operands.size() == 3) &&
36540b57cec5SDimitry Andric       (Name == "insb" || Name == "insw" || Name == "insl" || Name == "insd" ||
36550b57cec5SDimitry Andric        Name == "ins")) {
36560b57cec5SDimitry Andric 
36570b57cec5SDimitry Andric     AddDefaultSrcDestOperands(TmpOperands,
36580b57cec5SDimitry Andric                               X86Operand::CreateReg(X86::DX, NameLoc, NameLoc),
36590b57cec5SDimitry Andric                               DefaultMemDIOperand(NameLoc));
36600b57cec5SDimitry Andric     HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
36610b57cec5SDimitry Andric   }
36620b57cec5SDimitry Andric 
36630b57cec5SDimitry Andric   // Append default arguments to "outs[bwld]"
36645f757f3fSDimitry Andric   if (Name.starts_with("outs") &&
36650b57cec5SDimitry Andric       (Operands.size() == 1 || Operands.size() == 3) &&
36660b57cec5SDimitry Andric       (Name == "outsb" || Name == "outsw" || Name == "outsl" ||
36670b57cec5SDimitry Andric        Name == "outsd" || Name == "outs")) {
36680b57cec5SDimitry Andric     AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),
36690b57cec5SDimitry Andric                               X86Operand::CreateReg(X86::DX, NameLoc, NameLoc));
36700b57cec5SDimitry Andric     HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
36710b57cec5SDimitry Andric   }
36720b57cec5SDimitry Andric 
36730b57cec5SDimitry Andric   // Transform "lods[bwlq]" into "lods[bwlq] ($SIREG)" for appropriate
36740b57cec5SDimitry Andric   // values of $SIREG according to the mode. It would be nice if this
36750b57cec5SDimitry Andric   // could be achieved with InstAlias in the tables.
36765f757f3fSDimitry Andric   if (Name.starts_with("lods") &&
36770b57cec5SDimitry Andric       (Operands.size() == 1 || Operands.size() == 2) &&
36780b57cec5SDimitry Andric       (Name == "lods" || Name == "lodsb" || Name == "lodsw" ||
36790b57cec5SDimitry Andric        Name == "lodsl" || Name == "lodsd" || Name == "lodsq")) {
36800b57cec5SDimitry Andric     TmpOperands.push_back(DefaultMemSIOperand(NameLoc));
36810b57cec5SDimitry Andric     HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
36820b57cec5SDimitry Andric   }
36830b57cec5SDimitry Andric 
36840b57cec5SDimitry Andric   // Transform "stos[bwlq]" into "stos[bwlq] ($DIREG)" for appropriate
36850b57cec5SDimitry Andric   // values of $DIREG according to the mode. It would be nice if this
36860b57cec5SDimitry Andric   // could be achieved with InstAlias in the tables.
36875f757f3fSDimitry Andric   if (Name.starts_with("stos") &&
36880b57cec5SDimitry Andric       (Operands.size() == 1 || Operands.size() == 2) &&
36890b57cec5SDimitry Andric       (Name == "stos" || Name == "stosb" || Name == "stosw" ||
36900b57cec5SDimitry Andric        Name == "stosl" || Name == "stosd" || Name == "stosq")) {
36910b57cec5SDimitry Andric     TmpOperands.push_back(DefaultMemDIOperand(NameLoc));
36920b57cec5SDimitry Andric     HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
36930b57cec5SDimitry Andric   }
36940b57cec5SDimitry Andric 
36950b57cec5SDimitry Andric   // Transform "scas[bwlq]" into "scas[bwlq] ($DIREG)" for appropriate
36960b57cec5SDimitry Andric   // values of $DIREG according to the mode. It would be nice if this
36970b57cec5SDimitry Andric   // could be achieved with InstAlias in the tables.
36985f757f3fSDimitry Andric   if (Name.starts_with("scas") &&
36990b57cec5SDimitry Andric       (Operands.size() == 1 || Operands.size() == 2) &&
37000b57cec5SDimitry Andric       (Name == "scas" || Name == "scasb" || Name == "scasw" ||
37010b57cec5SDimitry Andric        Name == "scasl" || Name == "scasd" || Name == "scasq")) {
37020b57cec5SDimitry Andric     TmpOperands.push_back(DefaultMemDIOperand(NameLoc));
37030b57cec5SDimitry Andric     HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
37040b57cec5SDimitry Andric   }
37050b57cec5SDimitry Andric 
37060b57cec5SDimitry Andric   // Add default SI and DI operands to "cmps[bwlq]".
37075f757f3fSDimitry Andric   if (Name.starts_with("cmps") &&
37080b57cec5SDimitry Andric       (Operands.size() == 1 || Operands.size() == 3) &&
37090b57cec5SDimitry Andric       (Name == "cmps" || Name == "cmpsb" || Name == "cmpsw" ||
37100b57cec5SDimitry Andric        Name == "cmpsl" || Name == "cmpsd" || Name == "cmpsq")) {
37110b57cec5SDimitry Andric     AddDefaultSrcDestOperands(TmpOperands, DefaultMemDIOperand(NameLoc),
37120b57cec5SDimitry Andric                               DefaultMemSIOperand(NameLoc));
37130b57cec5SDimitry Andric     HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
37140b57cec5SDimitry Andric   }
37150b57cec5SDimitry Andric 
37160b57cec5SDimitry Andric   // Add default SI and DI operands to "movs[bwlq]".
37175f757f3fSDimitry Andric   if (((Name.starts_with("movs") &&
37180b57cec5SDimitry Andric         (Name == "movs" || Name == "movsb" || Name == "movsw" ||
37190b57cec5SDimitry Andric          Name == "movsl" || Name == "movsd" || Name == "movsq")) ||
37205f757f3fSDimitry Andric        (Name.starts_with("smov") &&
37210b57cec5SDimitry Andric         (Name == "smov" || Name == "smovb" || Name == "smovw" ||
37220b57cec5SDimitry Andric          Name == "smovl" || Name == "smovd" || Name == "smovq"))) &&
37230b57cec5SDimitry Andric       (Operands.size() == 1 || Operands.size() == 3)) {
37240b57cec5SDimitry Andric     if (Name == "movsd" && Operands.size() == 1 && !isParsingIntelSyntax())
37250b57cec5SDimitry Andric       Operands.back() = X86Operand::CreateToken("movsl", NameLoc);
37260b57cec5SDimitry Andric     AddDefaultSrcDestOperands(TmpOperands, DefaultMemSIOperand(NameLoc),
37270b57cec5SDimitry Andric                               DefaultMemDIOperand(NameLoc));
37280b57cec5SDimitry Andric     HadVerifyError = VerifyAndAdjustOperands(Operands, TmpOperands);
37290b57cec5SDimitry Andric   }
37300b57cec5SDimitry Andric 
37310b57cec5SDimitry Andric   // Check if we encountered an error for one the string insturctions
37320b57cec5SDimitry Andric   if (HadVerifyError) {
37330b57cec5SDimitry Andric     return HadVerifyError;
37340b57cec5SDimitry Andric   }
37350b57cec5SDimitry Andric 
37360b57cec5SDimitry Andric   // Transforms "xlat mem8" into "xlatb"
37370b57cec5SDimitry Andric   if ((Name == "xlat" || Name == "xlatb") && Operands.size() == 2) {
37380b57cec5SDimitry Andric     X86Operand &Op1 = static_cast<X86Operand &>(*Operands[1]);
37390b57cec5SDimitry Andric     if (Op1.isMem8()) {
37400b57cec5SDimitry Andric       Warning(Op1.getStartLoc(), "memory operand is only for determining the "
37410b57cec5SDimitry Andric                                  "size, (R|E)BX will be used for the location");
37420b57cec5SDimitry Andric       Operands.pop_back();
37430b57cec5SDimitry Andric       static_cast<X86Operand &>(*Operands[0]).setTokenValue("xlatb");
37440b57cec5SDimitry Andric     }
37450b57cec5SDimitry Andric   }
37460b57cec5SDimitry Andric 
37470b57cec5SDimitry Andric   if (Flags)
37480b57cec5SDimitry Andric     Operands.push_back(X86Operand::CreatePrefix(Flags, NameLoc, NameLoc));
37490b57cec5SDimitry Andric   return false;
37500b57cec5SDimitry Andric }
37510b57cec5SDimitry Andric 
convertSSEToAVX(MCInst & Inst)37520fca6ea1SDimitry Andric static bool convertSSEToAVX(MCInst &Inst) {
37530fca6ea1SDimitry Andric   ArrayRef<X86TableEntry> Table{X86SSE2AVXTable};
37540fca6ea1SDimitry Andric   unsigned Opcode = Inst.getOpcode();
37550fca6ea1SDimitry Andric   const auto I = llvm::lower_bound(Table, Opcode);
37560fca6ea1SDimitry Andric   if (I == Table.end() || I->OldOpc != Opcode)
37570fca6ea1SDimitry Andric     return false;
37580fca6ea1SDimitry Andric 
37590fca6ea1SDimitry Andric   Inst.setOpcode(I->NewOpc);
37600fca6ea1SDimitry Andric   // AVX variant of BLENDVPD/BLENDVPS/PBLENDVB instructions has more
37610fca6ea1SDimitry Andric   // operand compare to SSE variant, which is added below
37620fca6ea1SDimitry Andric   if (X86::isBLENDVPD(Opcode) || X86::isBLENDVPS(Opcode) ||
37630fca6ea1SDimitry Andric       X86::isPBLENDVB(Opcode))
37640fca6ea1SDimitry Andric     Inst.addOperand(Inst.getOperand(2));
37650fca6ea1SDimitry Andric 
37660fca6ea1SDimitry Andric   return true;
37670fca6ea1SDimitry Andric }
37680fca6ea1SDimitry Andric 
processInstruction(MCInst & Inst,const OperandVector & Ops)37690b57cec5SDimitry Andric bool X86AsmParser::processInstruction(MCInst &Inst, const OperandVector &Ops) {
37700fca6ea1SDimitry Andric   if (MCOptions.X86Sse2Avx && convertSSEToAVX(Inst))
37710fca6ea1SDimitry Andric     return true;
37720fca6ea1SDimitry Andric 
37730fca6ea1SDimitry Andric   if (ForcedOpcodePrefix != OpcodePrefix_VEX3 &&
377406c3fb27SDimitry Andric       X86::optimizeInstFromVEX3ToVEX2(Inst, MII.get(Inst.getOpcode())))
377506c3fb27SDimitry Andric     return true;
377606c3fb27SDimitry Andric 
377706c3fb27SDimitry Andric   if (X86::optimizeShiftRotateWithImmediateOne(Inst))
377806c3fb27SDimitry Andric     return true;
37790b57cec5SDimitry Andric 
37800b57cec5SDimitry Andric   switch (Inst.getOpcode()) {
37810b57cec5SDimitry Andric   default: return false;
3782e8d8bef9SDimitry Andric   case X86::JMP_1:
3783e8d8bef9SDimitry Andric     // {disp32} forces a larger displacement as if the instruction was relaxed.
3784e8d8bef9SDimitry Andric     // NOTE: 16-bit mode uses 16-bit displacement even though it says {disp32}.
3785e8d8bef9SDimitry Andric     // This matches GNU assembler.
3786e8d8bef9SDimitry Andric     if (ForcedDispEncoding == DispEncoding_Disp32) {
3787e8d8bef9SDimitry Andric       Inst.setOpcode(is16BitMode() ? X86::JMP_2 : X86::JMP_4);
3788e8d8bef9SDimitry Andric       return true;
3789e8d8bef9SDimitry Andric     }
3790e8d8bef9SDimitry Andric 
3791e8d8bef9SDimitry Andric     return false;
3792e8d8bef9SDimitry Andric   case X86::JCC_1:
3793e8d8bef9SDimitry Andric     // {disp32} forces a larger displacement as if the instruction was relaxed.
3794e8d8bef9SDimitry Andric     // NOTE: 16-bit mode uses 16-bit displacement even though it says {disp32}.
3795e8d8bef9SDimitry Andric     // This matches GNU assembler.
3796e8d8bef9SDimitry Andric     if (ForcedDispEncoding == DispEncoding_Disp32) {
3797e8d8bef9SDimitry Andric       Inst.setOpcode(is16BitMode() ? X86::JCC_2 : X86::JCC_4);
3798e8d8bef9SDimitry Andric       return true;
3799e8d8bef9SDimitry Andric     }
3800e8d8bef9SDimitry Andric 
3801e8d8bef9SDimitry Andric     return false;
3802e8d8bef9SDimitry Andric   case X86::INT: {
380306c3fb27SDimitry Andric     // Transforms "int $3" into "int3" as a size optimization.
380406c3fb27SDimitry Andric     // We can't write this as an InstAlias.
3805e8d8bef9SDimitry Andric     if (!Inst.getOperand(0).isImm() || Inst.getOperand(0).getImm() != 3)
3806e8d8bef9SDimitry Andric       return false;
380706c3fb27SDimitry Andric     Inst.clear();
380806c3fb27SDimitry Andric     Inst.setOpcode(X86::INT3);
3809e8d8bef9SDimitry Andric     return true;
3810e8d8bef9SDimitry Andric   }
38110b57cec5SDimitry Andric   }
38120b57cec5SDimitry Andric }
38130b57cec5SDimitry Andric 
validateInstruction(MCInst & Inst,const OperandVector & Ops)38140b57cec5SDimitry Andric bool X86AsmParser::validateInstruction(MCInst &Inst, const OperandVector &Ops) {
381581ad6265SDimitry Andric   using namespace X86;
38160b57cec5SDimitry Andric   const MCRegisterInfo *MRI = getContext().getRegisterInfo();
381781ad6265SDimitry Andric   unsigned Opcode = Inst.getOpcode();
381881ad6265SDimitry Andric   uint64_t TSFlags = MII.get(Opcode).TSFlags;
381981ad6265SDimitry Andric   if (isVFCMADDCPH(Opcode) || isVFCMADDCSH(Opcode) || isVFMADDCPH(Opcode) ||
382081ad6265SDimitry Andric       isVFMADDCSH(Opcode)) {
382181ad6265SDimitry Andric     unsigned Dest = Inst.getOperand(0).getReg();
382281ad6265SDimitry Andric     for (unsigned i = 2; i < Inst.getNumOperands(); i++)
382381ad6265SDimitry Andric       if (Inst.getOperand(i).isReg() && Dest == Inst.getOperand(i).getReg())
382481ad6265SDimitry Andric         return Warning(Ops[0]->getStartLoc(), "Destination register should be "
382581ad6265SDimitry Andric                                               "distinct from source registers");
382681ad6265SDimitry Andric   } else if (isVFCMULCPH(Opcode) || isVFCMULCSH(Opcode) || isVFMULCPH(Opcode) ||
382781ad6265SDimitry Andric              isVFMULCSH(Opcode)) {
382881ad6265SDimitry Andric     unsigned Dest = Inst.getOperand(0).getReg();
3829bdd1243dSDimitry Andric     // The mask variants have different operand list. Scan from the third
3830bdd1243dSDimitry Andric     // operand to avoid emitting incorrect warning.
3831bdd1243dSDimitry Andric     //    VFMULCPHZrr   Dest, Src1, Src2
3832bdd1243dSDimitry Andric     //    VFMULCPHZrrk  Dest, Dest, Mask, Src1, Src2
3833bdd1243dSDimitry Andric     //    VFMULCPHZrrkz Dest, Mask, Src1, Src2
38340fca6ea1SDimitry Andric     for (unsigned i = ((TSFlags & X86II::EVEX_K) ? 2 : 1);
3835bdd1243dSDimitry Andric          i < Inst.getNumOperands(); i++)
383681ad6265SDimitry Andric       if (Inst.getOperand(i).isReg() && Dest == Inst.getOperand(i).getReg())
383781ad6265SDimitry Andric         return Warning(Ops[0]->getStartLoc(), "Destination register should be "
383881ad6265SDimitry Andric                                               "distinct from source registers");
383981ad6265SDimitry Andric   } else if (isV4FMADDPS(Opcode) || isV4FMADDSS(Opcode) ||
384081ad6265SDimitry Andric              isV4FNMADDPS(Opcode) || isV4FNMADDSS(Opcode) ||
384181ad6265SDimitry Andric              isVP4DPWSSDS(Opcode) || isVP4DPWSSD(Opcode)) {
38420b57cec5SDimitry Andric     unsigned Src2 = Inst.getOperand(Inst.getNumOperands() -
38430b57cec5SDimitry Andric                                     X86::AddrNumOperands - 1).getReg();
38440b57cec5SDimitry Andric     unsigned Src2Enc = MRI->getEncodingValue(Src2);
38450b57cec5SDimitry Andric     if (Src2Enc % 4 != 0) {
38460b57cec5SDimitry Andric       StringRef RegName = X86IntelInstPrinter::getRegisterName(Src2);
38470b57cec5SDimitry Andric       unsigned GroupStart = (Src2Enc / 4) * 4;
38480b57cec5SDimitry Andric       unsigned GroupEnd = GroupStart + 3;
38490b57cec5SDimitry Andric       return Warning(Ops[0]->getStartLoc(),
38500b57cec5SDimitry Andric                      "source register '" + RegName + "' implicitly denotes '" +
38510b57cec5SDimitry Andric                      RegName.take_front(3) + Twine(GroupStart) + "' to '" +
38520b57cec5SDimitry Andric                      RegName.take_front(3) + Twine(GroupEnd) +
38530b57cec5SDimitry Andric                      "' source group");
38540b57cec5SDimitry Andric     }
385581ad6265SDimitry Andric   } else if (isVGATHERDPD(Opcode) || isVGATHERDPS(Opcode) ||
385681ad6265SDimitry Andric              isVGATHERQPD(Opcode) || isVGATHERQPS(Opcode) ||
385781ad6265SDimitry Andric              isVPGATHERDD(Opcode) || isVPGATHERDQ(Opcode) ||
385881ad6265SDimitry Andric              isVPGATHERQD(Opcode) || isVPGATHERQQ(Opcode)) {
385981ad6265SDimitry Andric     bool HasEVEX = (TSFlags & X86II::EncodingMask) == X86II::EVEX;
386081ad6265SDimitry Andric     if (HasEVEX) {
386181ad6265SDimitry Andric       unsigned Dest = MRI->getEncodingValue(Inst.getOperand(0).getReg());
386281ad6265SDimitry Andric       unsigned Index = MRI->getEncodingValue(
386381ad6265SDimitry Andric           Inst.getOperand(4 + X86::AddrIndexReg).getReg());
386481ad6265SDimitry Andric       if (Dest == Index)
386581ad6265SDimitry Andric         return Warning(Ops[0]->getStartLoc(), "index and destination registers "
386681ad6265SDimitry Andric                                               "should be distinct");
386781ad6265SDimitry Andric     } else {
386881ad6265SDimitry Andric       unsigned Dest = MRI->getEncodingValue(Inst.getOperand(0).getReg());
386981ad6265SDimitry Andric       unsigned Mask = MRI->getEncodingValue(Inst.getOperand(1).getReg());
387081ad6265SDimitry Andric       unsigned Index = MRI->getEncodingValue(
387181ad6265SDimitry Andric           Inst.getOperand(3 + X86::AddrIndexReg).getReg());
387281ad6265SDimitry Andric       if (Dest == Mask || Dest == Index || Mask == Index)
387381ad6265SDimitry Andric         return Warning(Ops[0]->getStartLoc(), "mask, index, and destination "
387481ad6265SDimitry Andric                                               "registers should be distinct");
3875349cc55cSDimitry Andric     }
38760fca6ea1SDimitry Andric   } else if (isTCMMIMFP16PS(Opcode) || isTCMMRLFP16PS(Opcode) ||
38770fca6ea1SDimitry Andric              isTDPBF16PS(Opcode) || isTDPFP16PS(Opcode) || isTDPBSSD(Opcode) ||
38780fca6ea1SDimitry Andric              isTDPBSUD(Opcode) || isTDPBUSD(Opcode) || isTDPBUUD(Opcode)) {
38790fca6ea1SDimitry Andric     unsigned SrcDest = Inst.getOperand(0).getReg();
38800fca6ea1SDimitry Andric     unsigned Src1 = Inst.getOperand(2).getReg();
38810fca6ea1SDimitry Andric     unsigned Src2 = Inst.getOperand(3).getReg();
38820fca6ea1SDimitry Andric     if (SrcDest == Src1 || SrcDest == Src2 || Src1 == Src2)
38830fca6ea1SDimitry Andric       return Error(Ops[0]->getStartLoc(), "all tmm registers must be distinct");
38840b57cec5SDimitry Andric   }
38850b57cec5SDimitry Andric 
3886e8d8bef9SDimitry Andric   // Check that we aren't mixing AH/BH/CH/DH with REX prefix. We only need to
3887e8d8bef9SDimitry Andric   // check this with the legacy encoding, VEX/EVEX/XOP don't use REX.
388881ad6265SDimitry Andric   if ((TSFlags & X86II::EncodingMask) == 0) {
3889e8d8bef9SDimitry Andric     MCPhysReg HReg = X86::NoRegister;
389081ad6265SDimitry Andric     bool UsesRex = TSFlags & X86II::REX_W;
3891e8d8bef9SDimitry Andric     unsigned NumOps = Inst.getNumOperands();
3892e8d8bef9SDimitry Andric     for (unsigned i = 0; i != NumOps; ++i) {
3893e8d8bef9SDimitry Andric       const MCOperand &MO = Inst.getOperand(i);
3894e8d8bef9SDimitry Andric       if (!MO.isReg())
3895e8d8bef9SDimitry Andric         continue;
3896e8d8bef9SDimitry Andric       unsigned Reg = MO.getReg();
3897e8d8bef9SDimitry Andric       if (Reg == X86::AH || Reg == X86::BH || Reg == X86::CH || Reg == X86::DH)
3898e8d8bef9SDimitry Andric         HReg = Reg;
3899e8d8bef9SDimitry Andric       if (X86II::isX86_64NonExtLowByteReg(Reg) ||
3900e8d8bef9SDimitry Andric           X86II::isX86_64ExtendedReg(Reg))
3901e8d8bef9SDimitry Andric         UsesRex = true;
3902e8d8bef9SDimitry Andric     }
3903e8d8bef9SDimitry Andric 
3904e8d8bef9SDimitry Andric     if (UsesRex && HReg != X86::NoRegister) {
3905e8d8bef9SDimitry Andric       StringRef RegName = X86IntelInstPrinter::getRegisterName(HReg);
3906e8d8bef9SDimitry Andric       return Error(Ops[0]->getStartLoc(),
3907e8d8bef9SDimitry Andric                    "can't encode '" + RegName + "' in an instruction requiring "
3908e8d8bef9SDimitry Andric                    "REX prefix");
3909e8d8bef9SDimitry Andric     }
3910e8d8bef9SDimitry Andric   }
3911e8d8bef9SDimitry Andric 
391206c3fb27SDimitry Andric   if ((Opcode == X86::PREFETCHIT0 || Opcode == X86::PREFETCHIT1)) {
391306c3fb27SDimitry Andric     const MCOperand &MO = Inst.getOperand(X86::AddrBaseReg);
391406c3fb27SDimitry Andric     if (!MO.isReg() || MO.getReg() != X86::RIP)
391506c3fb27SDimitry Andric       return Warning(
391606c3fb27SDimitry Andric           Ops[0]->getStartLoc(),
391706c3fb27SDimitry Andric           Twine((Inst.getOpcode() == X86::PREFETCHIT0 ? "'prefetchit0'"
391806c3fb27SDimitry Andric                                                       : "'prefetchit1'")) +
391906c3fb27SDimitry Andric               " only supports RIP-relative address");
392006c3fb27SDimitry Andric   }
39210b57cec5SDimitry Andric   return false;
39220b57cec5SDimitry Andric }
39230b57cec5SDimitry Andric 
emitWarningForSpecialLVIInstruction(SMLoc Loc)39245ffd83dbSDimitry Andric void X86AsmParser::emitWarningForSpecialLVIInstruction(SMLoc Loc) {
39255ffd83dbSDimitry Andric   Warning(Loc, "Instruction may be vulnerable to LVI and "
39265ffd83dbSDimitry Andric                "requires manual mitigation");
39275ffd83dbSDimitry Andric   Note(SMLoc(), "See https://software.intel.com/"
39285ffd83dbSDimitry Andric                 "security-software-guidance/insights/"
39295ffd83dbSDimitry Andric                 "deep-dive-load-value-injection#specialinstructions"
39305ffd83dbSDimitry Andric                 " for more information");
39315ffd83dbSDimitry Andric }
39325ffd83dbSDimitry Andric 
39335ffd83dbSDimitry Andric /// RET instructions and also instructions that indirect calls/jumps from memory
39345ffd83dbSDimitry Andric /// combine a load and a branch within a single instruction. To mitigate these
39355ffd83dbSDimitry Andric /// instructions against LVI, they must be decomposed into separate load and
39365ffd83dbSDimitry Andric /// branch instructions, with an LFENCE in between. For more details, see:
39375ffd83dbSDimitry Andric /// - X86LoadValueInjectionRetHardening.cpp
39385ffd83dbSDimitry Andric /// - X86LoadValueInjectionIndirectThunks.cpp
39395ffd83dbSDimitry Andric /// - https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection
39405ffd83dbSDimitry Andric ///
39415ffd83dbSDimitry Andric /// Returns `true` if a mitigation was applied or warning was emitted.
applyLVICFIMitigation(MCInst & Inst,MCStreamer & Out)39425ffd83dbSDimitry Andric void X86AsmParser::applyLVICFIMitigation(MCInst &Inst, MCStreamer &Out) {
39435ffd83dbSDimitry Andric   // Information on control-flow instructions that require manual mitigation can
39445ffd83dbSDimitry Andric   // be found here:
39455ffd83dbSDimitry Andric   // https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection#specialinstructions
39465ffd83dbSDimitry Andric   switch (Inst.getOpcode()) {
3947349cc55cSDimitry Andric   case X86::RET16:
3948349cc55cSDimitry Andric   case X86::RET32:
3949349cc55cSDimitry Andric   case X86::RET64:
3950349cc55cSDimitry Andric   case X86::RETI16:
3951349cc55cSDimitry Andric   case X86::RETI32:
3952349cc55cSDimitry Andric   case X86::RETI64: {
39535ffd83dbSDimitry Andric     MCInst ShlInst, FenceInst;
39545ffd83dbSDimitry Andric     bool Parse32 = is32BitMode() || Code16GCC;
39555ffd83dbSDimitry Andric     unsigned Basereg =
39565ffd83dbSDimitry Andric         is64BitMode() ? X86::RSP : (Parse32 ? X86::ESP : X86::SP);
39575ffd83dbSDimitry Andric     const MCExpr *Disp = MCConstantExpr::create(0, getContext());
39585ffd83dbSDimitry Andric     auto ShlMemOp = X86Operand::CreateMem(getPointerWidth(), /*SegReg=*/0, Disp,
39595ffd83dbSDimitry Andric                                           /*BaseReg=*/Basereg, /*IndexReg=*/0,
39605ffd83dbSDimitry Andric                                           /*Scale=*/1, SMLoc{}, SMLoc{}, 0);
39615ffd83dbSDimitry Andric     ShlInst.setOpcode(X86::SHL64mi);
39625ffd83dbSDimitry Andric     ShlMemOp->addMemOperands(ShlInst, 5);
39635ffd83dbSDimitry Andric     ShlInst.addOperand(MCOperand::createImm(0));
39645ffd83dbSDimitry Andric     FenceInst.setOpcode(X86::LFENCE);
39655ffd83dbSDimitry Andric     Out.emitInstruction(ShlInst, getSTI());
39665ffd83dbSDimitry Andric     Out.emitInstruction(FenceInst, getSTI());
39675ffd83dbSDimitry Andric     return;
39685ffd83dbSDimitry Andric   }
39695ffd83dbSDimitry Andric   case X86::JMP16m:
39705ffd83dbSDimitry Andric   case X86::JMP32m:
39715ffd83dbSDimitry Andric   case X86::JMP64m:
39725ffd83dbSDimitry Andric   case X86::CALL16m:
39735ffd83dbSDimitry Andric   case X86::CALL32m:
39745ffd83dbSDimitry Andric   case X86::CALL64m:
39755ffd83dbSDimitry Andric     emitWarningForSpecialLVIInstruction(Inst.getLoc());
39765ffd83dbSDimitry Andric     return;
39775ffd83dbSDimitry Andric   }
39785ffd83dbSDimitry Andric }
39795ffd83dbSDimitry Andric 
39805ffd83dbSDimitry Andric /// To mitigate LVI, every instruction that performs a load can be followed by
39815ffd83dbSDimitry Andric /// an LFENCE instruction to squash any potential mis-speculation. There are
39825ffd83dbSDimitry Andric /// some instructions that require additional considerations, and may requre
39835ffd83dbSDimitry Andric /// manual mitigation. For more details, see:
39845ffd83dbSDimitry Andric /// https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection
39855ffd83dbSDimitry Andric ///
39865ffd83dbSDimitry Andric /// Returns `true` if a mitigation was applied or warning was emitted.
applyLVILoadHardeningMitigation(MCInst & Inst,MCStreamer & Out)39875ffd83dbSDimitry Andric void X86AsmParser::applyLVILoadHardeningMitigation(MCInst &Inst,
39880b57cec5SDimitry Andric                                                    MCStreamer &Out) {
39895ffd83dbSDimitry Andric   auto Opcode = Inst.getOpcode();
39905ffd83dbSDimitry Andric   auto Flags = Inst.getFlags();
39915ffd83dbSDimitry Andric   if ((Flags & X86::IP_HAS_REPEAT) || (Flags & X86::IP_HAS_REPEAT_NE)) {
39925ffd83dbSDimitry Andric     // Information on REP string instructions that require manual mitigation can
39935ffd83dbSDimitry Andric     // be found here:
39945ffd83dbSDimitry Andric     // https://software.intel.com/security-software-guidance/insights/deep-dive-load-value-injection#specialinstructions
39955ffd83dbSDimitry Andric     switch (Opcode) {
39965ffd83dbSDimitry Andric     case X86::CMPSB:
39975ffd83dbSDimitry Andric     case X86::CMPSW:
39985ffd83dbSDimitry Andric     case X86::CMPSL:
39995ffd83dbSDimitry Andric     case X86::CMPSQ:
40005ffd83dbSDimitry Andric     case X86::SCASB:
40015ffd83dbSDimitry Andric     case X86::SCASW:
40025ffd83dbSDimitry Andric     case X86::SCASL:
40035ffd83dbSDimitry Andric     case X86::SCASQ:
40045ffd83dbSDimitry Andric       emitWarningForSpecialLVIInstruction(Inst.getLoc());
40055ffd83dbSDimitry Andric       return;
40065ffd83dbSDimitry Andric     }
40075ffd83dbSDimitry Andric   } else if (Opcode == X86::REP_PREFIX || Opcode == X86::REPNE_PREFIX) {
40085ffd83dbSDimitry Andric     // If a REP instruction is found on its own line, it may or may not be
40095ffd83dbSDimitry Andric     // followed by a vulnerable instruction. Emit a warning just in case.
40105ffd83dbSDimitry Andric     emitWarningForSpecialLVIInstruction(Inst.getLoc());
40115ffd83dbSDimitry Andric     return;
40125ffd83dbSDimitry Andric   }
40135ffd83dbSDimitry Andric 
40145ffd83dbSDimitry Andric   const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
40155ffd83dbSDimitry Andric 
40165ffd83dbSDimitry Andric   // Can't mitigate after terminators or calls. A control flow change may have
40175ffd83dbSDimitry Andric   // already occurred.
40185ffd83dbSDimitry Andric   if (MCID.isTerminator() || MCID.isCall())
40195ffd83dbSDimitry Andric     return;
40205ffd83dbSDimitry Andric 
40215ffd83dbSDimitry Andric   // LFENCE has the mayLoad property, don't double fence.
40225ffd83dbSDimitry Andric   if (MCID.mayLoad() && Inst.getOpcode() != X86::LFENCE) {
40235ffd83dbSDimitry Andric     MCInst FenceInst;
40245ffd83dbSDimitry Andric     FenceInst.setOpcode(X86::LFENCE);
40255ffd83dbSDimitry Andric     Out.emitInstruction(FenceInst, getSTI());
40265ffd83dbSDimitry Andric   }
40275ffd83dbSDimitry Andric }
40285ffd83dbSDimitry Andric 
emitInstruction(MCInst & Inst,OperandVector & Operands,MCStreamer & Out)40295ffd83dbSDimitry Andric void X86AsmParser::emitInstruction(MCInst &Inst, OperandVector &Operands,
40305ffd83dbSDimitry Andric                                    MCStreamer &Out) {
40315ffd83dbSDimitry Andric   if (LVIInlineAsmHardening &&
403206c3fb27SDimitry Andric       getSTI().hasFeature(X86::FeatureLVIControlFlowIntegrity))
40335ffd83dbSDimitry Andric     applyLVICFIMitigation(Inst, Out);
40345ffd83dbSDimitry Andric 
40355ffd83dbSDimitry Andric   Out.emitInstruction(Inst, getSTI());
40365ffd83dbSDimitry Andric 
40375ffd83dbSDimitry Andric   if (LVIInlineAsmHardening &&
403806c3fb27SDimitry Andric       getSTI().hasFeature(X86::FeatureLVILoadHardening))
40395ffd83dbSDimitry Andric     applyLVILoadHardeningMitigation(Inst, Out);
40400b57cec5SDimitry Andric }
40410b57cec5SDimitry Andric 
getPrefixes(OperandVector & Operands)40420fca6ea1SDimitry Andric static unsigned getPrefixes(OperandVector &Operands) {
40430fca6ea1SDimitry Andric   unsigned Result = 0;
40440fca6ea1SDimitry Andric   X86Operand &Prefix = static_cast<X86Operand &>(*Operands.back());
40450fca6ea1SDimitry Andric   if (Prefix.isPrefix()) {
40460fca6ea1SDimitry Andric     Result = Prefix.getPrefix();
40470fca6ea1SDimitry Andric     Operands.pop_back();
40480fca6ea1SDimitry Andric   }
40490fca6ea1SDimitry Andric   return Result;
40500fca6ea1SDimitry Andric }
40510fca6ea1SDimitry Andric 
MatchAndEmitInstruction(SMLoc IDLoc,unsigned & Opcode,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)40520b57cec5SDimitry Andric bool X86AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
40530b57cec5SDimitry Andric                                            OperandVector &Operands,
40540b57cec5SDimitry Andric                                            MCStreamer &Out, uint64_t &ErrorInfo,
40550b57cec5SDimitry Andric                                            bool MatchingInlineAsm) {
40560fca6ea1SDimitry Andric   assert(!Operands.empty() && "Unexpect empty operand list!");
40570fca6ea1SDimitry Andric   assert((*Operands[0]).isToken() && "Leading operand should always be a mnemonic!");
40580fca6ea1SDimitry Andric 
40590fca6ea1SDimitry Andric   // First, handle aliases that expand to multiple instructions.
40600fca6ea1SDimitry Andric   MatchFPUWaitAlias(IDLoc, static_cast<X86Operand &>(*Operands[0]), Operands,
40610fca6ea1SDimitry Andric                     Out, MatchingInlineAsm);
40620fca6ea1SDimitry Andric   unsigned Prefixes = getPrefixes(Operands);
40630fca6ea1SDimitry Andric 
40640fca6ea1SDimitry Andric   MCInst Inst;
40650fca6ea1SDimitry Andric 
40660fca6ea1SDimitry Andric   // If REX/REX2/VEX/EVEX encoding is forced, we need to pass the USE_* flag to
40670fca6ea1SDimitry Andric   // the encoder and printer.
40680fca6ea1SDimitry Andric   if (ForcedOpcodePrefix == OpcodePrefix_REX)
40690fca6ea1SDimitry Andric     Prefixes |= X86::IP_USE_REX;
40700fca6ea1SDimitry Andric   else if (ForcedOpcodePrefix == OpcodePrefix_REX2)
40710fca6ea1SDimitry Andric     Prefixes |= X86::IP_USE_REX2;
40720fca6ea1SDimitry Andric   else if (ForcedOpcodePrefix == OpcodePrefix_VEX)
40730fca6ea1SDimitry Andric     Prefixes |= X86::IP_USE_VEX;
40740fca6ea1SDimitry Andric   else if (ForcedOpcodePrefix == OpcodePrefix_VEX2)
40750fca6ea1SDimitry Andric     Prefixes |= X86::IP_USE_VEX2;
40760fca6ea1SDimitry Andric   else if (ForcedOpcodePrefix == OpcodePrefix_VEX3)
40770fca6ea1SDimitry Andric     Prefixes |= X86::IP_USE_VEX3;
40780fca6ea1SDimitry Andric   else if (ForcedOpcodePrefix == OpcodePrefix_EVEX)
40790fca6ea1SDimitry Andric     Prefixes |= X86::IP_USE_EVEX;
40800fca6ea1SDimitry Andric 
40810fca6ea1SDimitry Andric   // Set encoded flags for {disp8} and {disp32}.
40820fca6ea1SDimitry Andric   if (ForcedDispEncoding == DispEncoding_Disp8)
40830fca6ea1SDimitry Andric     Prefixes |= X86::IP_USE_DISP8;
40840fca6ea1SDimitry Andric   else if (ForcedDispEncoding == DispEncoding_Disp32)
40850fca6ea1SDimitry Andric     Prefixes |= X86::IP_USE_DISP32;
40860fca6ea1SDimitry Andric 
40870fca6ea1SDimitry Andric   if (Prefixes)
40880fca6ea1SDimitry Andric     Inst.setFlags(Prefixes);
40890fca6ea1SDimitry Andric 
40900fca6ea1SDimitry Andric   return isParsingIntelSyntax()
40910fca6ea1SDimitry Andric              ? matchAndEmitIntelInstruction(IDLoc, Opcode, Inst, Operands, Out,
40920fca6ea1SDimitry Andric                                             ErrorInfo, MatchingInlineAsm)
40930fca6ea1SDimitry Andric              : matchAndEmitATTInstruction(IDLoc, Opcode, Inst, Operands, Out,
40940fca6ea1SDimitry Andric                                           ErrorInfo, MatchingInlineAsm);
40950b57cec5SDimitry Andric }
40960b57cec5SDimitry Andric 
MatchFPUWaitAlias(SMLoc IDLoc,X86Operand & Op,OperandVector & Operands,MCStreamer & Out,bool MatchingInlineAsm)40970b57cec5SDimitry Andric void X86AsmParser::MatchFPUWaitAlias(SMLoc IDLoc, X86Operand &Op,
40980b57cec5SDimitry Andric                                      OperandVector &Operands, MCStreamer &Out,
40990b57cec5SDimitry Andric                                      bool MatchingInlineAsm) {
41000b57cec5SDimitry Andric   // FIXME: This should be replaced with a real .td file alias mechanism.
41010b57cec5SDimitry Andric   // Also, MatchInstructionImpl should actually *do* the EmitInstruction
41020b57cec5SDimitry Andric   // call.
41030b57cec5SDimitry Andric   const char *Repl = StringSwitch<const char *>(Op.getToken())
41040b57cec5SDimitry Andric                          .Case("finit", "fninit")
41050b57cec5SDimitry Andric                          .Case("fsave", "fnsave")
41060b57cec5SDimitry Andric                          .Case("fstcw", "fnstcw")
41070b57cec5SDimitry Andric                          .Case("fstcww", "fnstcw")
41080b57cec5SDimitry Andric                          .Case("fstenv", "fnstenv")
41090b57cec5SDimitry Andric                          .Case("fstsw", "fnstsw")
41100b57cec5SDimitry Andric                          .Case("fstsww", "fnstsw")
41110b57cec5SDimitry Andric                          .Case("fclex", "fnclex")
41120b57cec5SDimitry Andric                          .Default(nullptr);
41130b57cec5SDimitry Andric   if (Repl) {
41140b57cec5SDimitry Andric     MCInst Inst;
41150b57cec5SDimitry Andric     Inst.setOpcode(X86::WAIT);
41160b57cec5SDimitry Andric     Inst.setLoc(IDLoc);
41170b57cec5SDimitry Andric     if (!MatchingInlineAsm)
41185ffd83dbSDimitry Andric       emitInstruction(Inst, Operands, Out);
41190b57cec5SDimitry Andric     Operands[0] = X86Operand::CreateToken(Repl, IDLoc);
41200b57cec5SDimitry Andric   }
41210b57cec5SDimitry Andric }
41220b57cec5SDimitry Andric 
ErrorMissingFeature(SMLoc IDLoc,const FeatureBitset & MissingFeatures,bool MatchingInlineAsm)41230b57cec5SDimitry Andric bool X86AsmParser::ErrorMissingFeature(SMLoc IDLoc,
41240b57cec5SDimitry Andric                                        const FeatureBitset &MissingFeatures,
41250b57cec5SDimitry Andric                                        bool MatchingInlineAsm) {
41260b57cec5SDimitry Andric   assert(MissingFeatures.any() && "Unknown missing feature!");
41270b57cec5SDimitry Andric   SmallString<126> Msg;
41280b57cec5SDimitry Andric   raw_svector_ostream OS(Msg);
41290b57cec5SDimitry Andric   OS << "instruction requires:";
41300b57cec5SDimitry Andric   for (unsigned i = 0, e = MissingFeatures.size(); i != e; ++i) {
41310b57cec5SDimitry Andric     if (MissingFeatures[i])
41320b57cec5SDimitry Andric       OS << ' ' << getSubtargetFeatureName(i);
41330b57cec5SDimitry Andric   }
41340b57cec5SDimitry Andric   return Error(IDLoc, OS.str(), SMRange(), MatchingInlineAsm);
41350b57cec5SDimitry Andric }
41360b57cec5SDimitry Andric 
checkTargetMatchPredicate(MCInst & Inst)41370b57cec5SDimitry Andric unsigned X86AsmParser::checkTargetMatchPredicate(MCInst &Inst) {
41380b57cec5SDimitry Andric   unsigned Opc = Inst.getOpcode();
41390b57cec5SDimitry Andric   const MCInstrDesc &MCID = MII.get(Opc);
41400fca6ea1SDimitry Andric   uint64_t TSFlags = MCID.TSFlags;
41410b57cec5SDimitry Andric 
41425f757f3fSDimitry Andric   if (UseApxExtendedReg && !X86II::canUseApxExtendedReg(MCID))
41435f757f3fSDimitry Andric     return Match_Unsupported;
41440fca6ea1SDimitry Andric   if (ForcedNoFlag == !(TSFlags & X86II::EVEX_NF) && !X86::isCFCMOVCC(Opc))
4145647cbc5dSDimitry Andric     return Match_Unsupported;
41465f757f3fSDimitry Andric 
41470fca6ea1SDimitry Andric   switch (ForcedOpcodePrefix) {
41480fca6ea1SDimitry Andric   case OpcodePrefix_Default:
41490fca6ea1SDimitry Andric     break;
41500fca6ea1SDimitry Andric   case OpcodePrefix_REX:
41510fca6ea1SDimitry Andric   case OpcodePrefix_REX2:
41520fca6ea1SDimitry Andric     if (TSFlags & X86II::EncodingMask)
41530b57cec5SDimitry Andric       return Match_Unsupported;
41540fca6ea1SDimitry Andric     break;
41550fca6ea1SDimitry Andric   case OpcodePrefix_VEX:
41560fca6ea1SDimitry Andric   case OpcodePrefix_VEX2:
41570fca6ea1SDimitry Andric   case OpcodePrefix_VEX3:
41580fca6ea1SDimitry Andric     if ((TSFlags & X86II::EncodingMask) != X86II::VEX)
41590b57cec5SDimitry Andric       return Match_Unsupported;
41600fca6ea1SDimitry Andric     break;
41610fca6ea1SDimitry Andric   case OpcodePrefix_EVEX:
41620fca6ea1SDimitry Andric     if ((TSFlags & X86II::EncodingMask) != X86II::EVEX)
41630fca6ea1SDimitry Andric       return Match_Unsupported;
41640fca6ea1SDimitry Andric     break;
41650fca6ea1SDimitry Andric   }
41660b57cec5SDimitry Andric 
41670fca6ea1SDimitry Andric   if ((TSFlags & X86II::ExplicitOpPrefixMask) == X86II::ExplicitVEXPrefix &&
41680fca6ea1SDimitry Andric       (ForcedOpcodePrefix != OpcodePrefix_VEX &&
41690fca6ea1SDimitry Andric        ForcedOpcodePrefix != OpcodePrefix_VEX2 &&
41700fca6ea1SDimitry Andric        ForcedOpcodePrefix != OpcodePrefix_VEX3))
4171e8d8bef9SDimitry Andric     return Match_Unsupported;
4172e8d8bef9SDimitry Andric 
41730b57cec5SDimitry Andric   return Match_Success;
41740b57cec5SDimitry Andric }
41750b57cec5SDimitry Andric 
matchAndEmitATTInstruction(SMLoc IDLoc,unsigned & Opcode,MCInst & Inst,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)41760fca6ea1SDimitry Andric bool X86AsmParser::matchAndEmitATTInstruction(
41770fca6ea1SDimitry Andric     SMLoc IDLoc, unsigned &Opcode, MCInst &Inst, OperandVector &Operands,
41780fca6ea1SDimitry Andric     MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) {
41790b57cec5SDimitry Andric   X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);
41800fca6ea1SDimitry Andric   SMRange EmptyRange = std::nullopt;
4181e8d8bef9SDimitry Andric   // In 16-bit mode, if data32 is specified, temporarily switch to 32-bit mode
4182e8d8bef9SDimitry Andric   // when matching the instruction.
418381ad6265SDimitry Andric   if (ForcedDataPrefix == X86::Is32Bit)
418481ad6265SDimitry Andric     SwitchMode(X86::Is32Bit);
41850b57cec5SDimitry Andric   // First, try a direct match.
41860b57cec5SDimitry Andric   FeatureBitset MissingFeatures;
41870b57cec5SDimitry Andric   unsigned OriginalError = MatchInstruction(Operands, Inst, ErrorInfo,
41880b57cec5SDimitry Andric                                             MissingFeatures, MatchingInlineAsm,
41890b57cec5SDimitry Andric                                             isParsingIntelSyntax());
419081ad6265SDimitry Andric   if (ForcedDataPrefix == X86::Is32Bit) {
419181ad6265SDimitry Andric     SwitchMode(X86::Is16Bit);
4192e8d8bef9SDimitry Andric     ForcedDataPrefix = 0;
4193e8d8bef9SDimitry Andric   }
41940b57cec5SDimitry Andric   switch (OriginalError) {
41950b57cec5SDimitry Andric   default: llvm_unreachable("Unexpected match result!");
41960b57cec5SDimitry Andric   case Match_Success:
41970b57cec5SDimitry Andric     if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
41980b57cec5SDimitry Andric       return true;
41990b57cec5SDimitry Andric     // Some instructions need post-processing to, for example, tweak which
42000b57cec5SDimitry Andric     // encoding is selected. Loop on it while changes happen so the
42010b57cec5SDimitry Andric     // individual transformations can chain off each other.
42020b57cec5SDimitry Andric     if (!MatchingInlineAsm)
42030b57cec5SDimitry Andric       while (processInstruction(Inst, Operands))
42040b57cec5SDimitry Andric         ;
42050b57cec5SDimitry Andric 
42060b57cec5SDimitry Andric     Inst.setLoc(IDLoc);
42070b57cec5SDimitry Andric     if (!MatchingInlineAsm)
42085ffd83dbSDimitry Andric       emitInstruction(Inst, Operands, Out);
42090b57cec5SDimitry Andric     Opcode = Inst.getOpcode();
42100b57cec5SDimitry Andric     return false;
42118bcb0991SDimitry Andric   case Match_InvalidImmUnsignedi4: {
42128bcb0991SDimitry Andric     SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc();
42138bcb0991SDimitry Andric     if (ErrorLoc == SMLoc())
42148bcb0991SDimitry Andric       ErrorLoc = IDLoc;
42158bcb0991SDimitry Andric     return Error(ErrorLoc, "immediate must be an integer in range [0, 15]",
42168bcb0991SDimitry Andric                  EmptyRange, MatchingInlineAsm);
42178bcb0991SDimitry Andric   }
42180b57cec5SDimitry Andric   case Match_MissingFeature:
42190b57cec5SDimitry Andric     return ErrorMissingFeature(IDLoc, MissingFeatures, MatchingInlineAsm);
42200b57cec5SDimitry Andric   case Match_InvalidOperand:
42210b57cec5SDimitry Andric   case Match_MnemonicFail:
42220b57cec5SDimitry Andric   case Match_Unsupported:
42230b57cec5SDimitry Andric     break;
42240b57cec5SDimitry Andric   }
42250b57cec5SDimitry Andric   if (Op.getToken().empty()) {
42260b57cec5SDimitry Andric     Error(IDLoc, "instruction must have size higher than 0", EmptyRange,
42270b57cec5SDimitry Andric           MatchingInlineAsm);
42280b57cec5SDimitry Andric     return true;
42290b57cec5SDimitry Andric   }
42300b57cec5SDimitry Andric 
42310b57cec5SDimitry Andric   // FIXME: Ideally, we would only attempt suffix matches for things which are
42320b57cec5SDimitry Andric   // valid prefixes, and we could just infer the right unambiguous
42330b57cec5SDimitry Andric   // type. However, that requires substantially more matcher support than the
42340b57cec5SDimitry Andric   // following hack.
42350b57cec5SDimitry Andric 
42360b57cec5SDimitry Andric   // Change the operand to point to a temporary token.
42370b57cec5SDimitry Andric   StringRef Base = Op.getToken();
42380b57cec5SDimitry Andric   SmallString<16> Tmp;
42390b57cec5SDimitry Andric   Tmp += Base;
42400b57cec5SDimitry Andric   Tmp += ' ';
42410b57cec5SDimitry Andric   Op.setTokenValue(Tmp);
42420b57cec5SDimitry Andric 
42430b57cec5SDimitry Andric   // If this instruction starts with an 'f', then it is a floating point stack
42440b57cec5SDimitry Andric   // instruction.  These come in up to three forms for 32-bit, 64-bit, and
42450b57cec5SDimitry Andric   // 80-bit floating point, which use the suffixes s,l,t respectively.
42460b57cec5SDimitry Andric   //
42470b57cec5SDimitry Andric   // Otherwise, we assume that this may be an integer instruction, which comes
42480b57cec5SDimitry Andric   // in 8/16/32/64-bit forms using the b,w,l,q suffixes respectively.
42490b57cec5SDimitry Andric   const char *Suffixes = Base[0] != 'f' ? "bwlq" : "slt\0";
42505ffd83dbSDimitry Andric   // MemSize corresponding to Suffixes.  { 8, 16, 32, 64 }    { 32, 64, 80, 0 }
42515ffd83dbSDimitry Andric   const char *MemSize = Base[0] != 'f' ? "\x08\x10\x20\x40" : "\x20\x40\x50\0";
42520b57cec5SDimitry Andric 
42530b57cec5SDimitry Andric   // Check for the various suffix matches.
42540b57cec5SDimitry Andric   uint64_t ErrorInfoIgnore;
42550b57cec5SDimitry Andric   FeatureBitset ErrorInfoMissingFeatures; // Init suppresses compiler warnings.
42560b57cec5SDimitry Andric   unsigned Match[4];
42570b57cec5SDimitry Andric 
42585ffd83dbSDimitry Andric   // Some instruction like VPMULDQ is NOT the variant of VPMULD but a new one.
42595ffd83dbSDimitry Andric   // So we should make sure the suffix matcher only works for memory variant
42605ffd83dbSDimitry Andric   // that has the same size with the suffix.
42615ffd83dbSDimitry Andric   // FIXME: This flag is a workaround for legacy instructions that didn't
42625ffd83dbSDimitry Andric   // declare non suffix variant assembly.
42635ffd83dbSDimitry Andric   bool HasVectorReg = false;
42645ffd83dbSDimitry Andric   X86Operand *MemOp = nullptr;
42655ffd83dbSDimitry Andric   for (const auto &Op : Operands) {
42665ffd83dbSDimitry Andric     X86Operand *X86Op = static_cast<X86Operand *>(Op.get());
42675ffd83dbSDimitry Andric     if (X86Op->isVectorReg())
42685ffd83dbSDimitry Andric       HasVectorReg = true;
42695ffd83dbSDimitry Andric     else if (X86Op->isMem()) {
42705ffd83dbSDimitry Andric       MemOp = X86Op;
42715ffd83dbSDimitry Andric       assert(MemOp->Mem.Size == 0 && "Memory size always 0 under ATT syntax");
42725ffd83dbSDimitry Andric       // Have we found an unqualified memory operand,
42735ffd83dbSDimitry Andric       // break. IA allows only one memory operand.
42745ffd83dbSDimitry Andric       break;
42755ffd83dbSDimitry Andric     }
42765ffd83dbSDimitry Andric   }
42775ffd83dbSDimitry Andric 
4278bdd1243dSDimitry Andric   for (unsigned I = 0, E = std::size(Match); I != E; ++I) {
42790b57cec5SDimitry Andric     Tmp.back() = Suffixes[I];
42805ffd83dbSDimitry Andric     if (MemOp && HasVectorReg)
42815ffd83dbSDimitry Andric       MemOp->Mem.Size = MemSize[I];
42825ffd83dbSDimitry Andric     Match[I] = Match_MnemonicFail;
42835ffd83dbSDimitry Andric     if (MemOp || !HasVectorReg) {
42845ffd83dbSDimitry Andric       Match[I] =
42855ffd83dbSDimitry Andric           MatchInstruction(Operands, Inst, ErrorInfoIgnore, MissingFeatures,
42865ffd83dbSDimitry Andric                            MatchingInlineAsm, isParsingIntelSyntax());
42870b57cec5SDimitry Andric       // If this returned as a missing feature failure, remember that.
42880b57cec5SDimitry Andric       if (Match[I] == Match_MissingFeature)
42890b57cec5SDimitry Andric         ErrorInfoMissingFeatures = MissingFeatures;
42900b57cec5SDimitry Andric     }
42915ffd83dbSDimitry Andric   }
42920b57cec5SDimitry Andric 
42930b57cec5SDimitry Andric   // Restore the old token.
42940b57cec5SDimitry Andric   Op.setTokenValue(Base);
42950b57cec5SDimitry Andric 
42960b57cec5SDimitry Andric   // If exactly one matched, then we treat that as a successful match (and the
42970b57cec5SDimitry Andric   // instruction will already have been filled in correctly, since the failing
42980b57cec5SDimitry Andric   // matches won't have modified it).
42990eae32dcSDimitry Andric   unsigned NumSuccessfulMatches = llvm::count(Match, Match_Success);
43000b57cec5SDimitry Andric   if (NumSuccessfulMatches == 1) {
4301e8d8bef9SDimitry Andric     if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
4302e8d8bef9SDimitry Andric       return true;
4303e8d8bef9SDimitry Andric     // Some instructions need post-processing to, for example, tweak which
4304e8d8bef9SDimitry Andric     // encoding is selected. Loop on it while changes happen so the
4305e8d8bef9SDimitry Andric     // individual transformations can chain off each other.
4306e8d8bef9SDimitry Andric     if (!MatchingInlineAsm)
4307e8d8bef9SDimitry Andric       while (processInstruction(Inst, Operands))
4308e8d8bef9SDimitry Andric         ;
4309e8d8bef9SDimitry Andric 
43100b57cec5SDimitry Andric     Inst.setLoc(IDLoc);
43110b57cec5SDimitry Andric     if (!MatchingInlineAsm)
43125ffd83dbSDimitry Andric       emitInstruction(Inst, Operands, Out);
43130b57cec5SDimitry Andric     Opcode = Inst.getOpcode();
43140b57cec5SDimitry Andric     return false;
43150b57cec5SDimitry Andric   }
43160b57cec5SDimitry Andric 
43170b57cec5SDimitry Andric   // Otherwise, the match failed, try to produce a decent error message.
43180b57cec5SDimitry Andric 
43190b57cec5SDimitry Andric   // If we had multiple suffix matches, then identify this as an ambiguous
43200b57cec5SDimitry Andric   // match.
43210b57cec5SDimitry Andric   if (NumSuccessfulMatches > 1) {
43220b57cec5SDimitry Andric     char MatchChars[4];
43230b57cec5SDimitry Andric     unsigned NumMatches = 0;
4324bdd1243dSDimitry Andric     for (unsigned I = 0, E = std::size(Match); I != E; ++I)
43250b57cec5SDimitry Andric       if (Match[I] == Match_Success)
43260b57cec5SDimitry Andric         MatchChars[NumMatches++] = Suffixes[I];
43270b57cec5SDimitry Andric 
43280b57cec5SDimitry Andric     SmallString<126> Msg;
43290b57cec5SDimitry Andric     raw_svector_ostream OS(Msg);
43300b57cec5SDimitry Andric     OS << "ambiguous instructions require an explicit suffix (could be ";
43310b57cec5SDimitry Andric     for (unsigned i = 0; i != NumMatches; ++i) {
43320b57cec5SDimitry Andric       if (i != 0)
43330b57cec5SDimitry Andric         OS << ", ";
43340b57cec5SDimitry Andric       if (i + 1 == NumMatches)
43350b57cec5SDimitry Andric         OS << "or ";
43360b57cec5SDimitry Andric       OS << "'" << Base << MatchChars[i] << "'";
43370b57cec5SDimitry Andric     }
43380b57cec5SDimitry Andric     OS << ")";
43390b57cec5SDimitry Andric     Error(IDLoc, OS.str(), EmptyRange, MatchingInlineAsm);
43400b57cec5SDimitry Andric     return true;
43410b57cec5SDimitry Andric   }
43420b57cec5SDimitry Andric 
43430b57cec5SDimitry Andric   // Okay, we know that none of the variants matched successfully.
43440b57cec5SDimitry Andric 
43450b57cec5SDimitry Andric   // If all of the instructions reported an invalid mnemonic, then the original
43460b57cec5SDimitry Andric   // mnemonic was invalid.
43470eae32dcSDimitry Andric   if (llvm::count(Match, Match_MnemonicFail) == 4) {
43480b57cec5SDimitry Andric     if (OriginalError == Match_MnemonicFail)
43490b57cec5SDimitry Andric       return Error(IDLoc, "invalid instruction mnemonic '" + Base + "'",
43500b57cec5SDimitry Andric                    Op.getLocRange(), MatchingInlineAsm);
43510b57cec5SDimitry Andric 
43520b57cec5SDimitry Andric     if (OriginalError == Match_Unsupported)
43530b57cec5SDimitry Andric       return Error(IDLoc, "unsupported instruction", EmptyRange,
43540b57cec5SDimitry Andric                    MatchingInlineAsm);
43550b57cec5SDimitry Andric 
43560b57cec5SDimitry Andric     assert(OriginalError == Match_InvalidOperand && "Unexpected error");
43570b57cec5SDimitry Andric     // Recover location info for the operand if we know which was the problem.
43580b57cec5SDimitry Andric     if (ErrorInfo != ~0ULL) {
43590b57cec5SDimitry Andric       if (ErrorInfo >= Operands.size())
43600b57cec5SDimitry Andric         return Error(IDLoc, "too few operands for instruction", EmptyRange,
43610b57cec5SDimitry Andric                      MatchingInlineAsm);
43620b57cec5SDimitry Andric 
43630b57cec5SDimitry Andric       X86Operand &Operand = (X86Operand &)*Operands[ErrorInfo];
43640b57cec5SDimitry Andric       if (Operand.getStartLoc().isValid()) {
43650b57cec5SDimitry Andric         SMRange OperandRange = Operand.getLocRange();
43660b57cec5SDimitry Andric         return Error(Operand.getStartLoc(), "invalid operand for instruction",
43670b57cec5SDimitry Andric                      OperandRange, MatchingInlineAsm);
43680b57cec5SDimitry Andric       }
43690b57cec5SDimitry Andric     }
43700b57cec5SDimitry Andric 
43710b57cec5SDimitry Andric     return Error(IDLoc, "invalid operand for instruction", EmptyRange,
43720b57cec5SDimitry Andric                  MatchingInlineAsm);
43730b57cec5SDimitry Andric   }
43740b57cec5SDimitry Andric 
43750b57cec5SDimitry Andric   // If one instruction matched as unsupported, report this as unsupported.
43760eae32dcSDimitry Andric   if (llvm::count(Match, Match_Unsupported) == 1) {
43770b57cec5SDimitry Andric     return Error(IDLoc, "unsupported instruction", EmptyRange,
43780b57cec5SDimitry Andric                  MatchingInlineAsm);
43790b57cec5SDimitry Andric   }
43800b57cec5SDimitry Andric 
43810b57cec5SDimitry Andric   // If one instruction matched with a missing feature, report this as a
43820b57cec5SDimitry Andric   // missing feature.
43830eae32dcSDimitry Andric   if (llvm::count(Match, Match_MissingFeature) == 1) {
43840b57cec5SDimitry Andric     ErrorInfo = Match_MissingFeature;
43850b57cec5SDimitry Andric     return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures,
43860b57cec5SDimitry Andric                                MatchingInlineAsm);
43870b57cec5SDimitry Andric   }
43880b57cec5SDimitry Andric 
43890b57cec5SDimitry Andric   // If one instruction matched with an invalid operand, report this as an
43900b57cec5SDimitry Andric   // operand failure.
43910eae32dcSDimitry Andric   if (llvm::count(Match, Match_InvalidOperand) == 1) {
43920b57cec5SDimitry Andric     return Error(IDLoc, "invalid operand for instruction", EmptyRange,
43930b57cec5SDimitry Andric                  MatchingInlineAsm);
43940b57cec5SDimitry Andric   }
43950b57cec5SDimitry Andric 
43960b57cec5SDimitry Andric   // If all of these were an outright failure, report it in a useless way.
43970b57cec5SDimitry Andric   Error(IDLoc, "unknown use of instruction mnemonic without a size suffix",
43980b57cec5SDimitry Andric         EmptyRange, MatchingInlineAsm);
43990b57cec5SDimitry Andric   return true;
44000b57cec5SDimitry Andric }
44010b57cec5SDimitry Andric 
matchAndEmitIntelInstruction(SMLoc IDLoc,unsigned & Opcode,MCInst & Inst,OperandVector & Operands,MCStreamer & Out,uint64_t & ErrorInfo,bool MatchingInlineAsm)44020fca6ea1SDimitry Andric bool X86AsmParser::matchAndEmitIntelInstruction(
44030fca6ea1SDimitry Andric     SMLoc IDLoc, unsigned &Opcode, MCInst &Inst, OperandVector &Operands,
44040fca6ea1SDimitry Andric     MCStreamer &Out, uint64_t &ErrorInfo, bool MatchingInlineAsm) {
44050b57cec5SDimitry Andric   X86Operand &Op = static_cast<X86Operand &>(*Operands[0]);
44060fca6ea1SDimitry Andric   SMRange EmptyRange = std::nullopt;
44070b57cec5SDimitry Andric   // Find one unsized memory operand, if present.
44080b57cec5SDimitry Andric   X86Operand *UnsizedMemOp = nullptr;
44090b57cec5SDimitry Andric   for (const auto &Op : Operands) {
44100b57cec5SDimitry Andric     X86Operand *X86Op = static_cast<X86Operand *>(Op.get());
44110b57cec5SDimitry Andric     if (X86Op->isMemUnsized()) {
44120b57cec5SDimitry Andric       UnsizedMemOp = X86Op;
44130b57cec5SDimitry Andric       // Have we found an unqualified memory operand,
44140b57cec5SDimitry Andric       // break. IA allows only one memory operand.
44150b57cec5SDimitry Andric       break;
44160b57cec5SDimitry Andric     }
44170b57cec5SDimitry Andric   }
44180b57cec5SDimitry Andric 
44190b57cec5SDimitry Andric   // Allow some instructions to have implicitly pointer-sized operands.  This is
44200b57cec5SDimitry Andric   // compatible with gas.
44210fca6ea1SDimitry Andric   StringRef Mnemonic = (static_cast<X86Operand &>(*Operands[0])).getToken();
44220b57cec5SDimitry Andric   if (UnsizedMemOp) {
44230b57cec5SDimitry Andric     static const char *const PtrSizedInstrs[] = {"call", "jmp", "push"};
44240b57cec5SDimitry Andric     for (const char *Instr : PtrSizedInstrs) {
44250b57cec5SDimitry Andric       if (Mnemonic == Instr) {
44260b57cec5SDimitry Andric         UnsizedMemOp->Mem.Size = getPointerWidth();
44270b57cec5SDimitry Andric         break;
44280b57cec5SDimitry Andric       }
44290b57cec5SDimitry Andric     }
44300b57cec5SDimitry Andric   }
44310b57cec5SDimitry Andric 
44320b57cec5SDimitry Andric   SmallVector<unsigned, 8> Match;
44330b57cec5SDimitry Andric   FeatureBitset ErrorInfoMissingFeatures;
44340b57cec5SDimitry Andric   FeatureBitset MissingFeatures;
44350fca6ea1SDimitry Andric   StringRef Base = (static_cast<X86Operand &>(*Operands[0])).getToken();
44360b57cec5SDimitry Andric 
44370b57cec5SDimitry Andric   // If unsized push has immediate operand we should default the default pointer
44380b57cec5SDimitry Andric   // size for the size.
44390b57cec5SDimitry Andric   if (Mnemonic == "push" && Operands.size() == 2) {
44400b57cec5SDimitry Andric     auto *X86Op = static_cast<X86Operand *>(Operands[1].get());
44410b57cec5SDimitry Andric     if (X86Op->isImm()) {
44420b57cec5SDimitry Andric       // If it's not a constant fall through and let remainder take care of it.
44430b57cec5SDimitry Andric       const auto *CE = dyn_cast<MCConstantExpr>(X86Op->getImm());
44440b57cec5SDimitry Andric       unsigned Size = getPointerWidth();
44450b57cec5SDimitry Andric       if (CE &&
44460b57cec5SDimitry Andric           (isIntN(Size, CE->getValue()) || isUIntN(Size, CE->getValue()))) {
44470b57cec5SDimitry Andric         SmallString<16> Tmp;
44480b57cec5SDimitry Andric         Tmp += Base;
44490b57cec5SDimitry Andric         Tmp += (is64BitMode())
44500b57cec5SDimitry Andric                    ? "q"
44510b57cec5SDimitry Andric                    : (is32BitMode()) ? "l" : (is16BitMode()) ? "w" : " ";
44520b57cec5SDimitry Andric         Op.setTokenValue(Tmp);
44530b57cec5SDimitry Andric         // Do match in ATT mode to allow explicit suffix usage.
44540b57cec5SDimitry Andric         Match.push_back(MatchInstruction(Operands, Inst, ErrorInfo,
44550b57cec5SDimitry Andric                                          MissingFeatures, MatchingInlineAsm,
44560b57cec5SDimitry Andric                                          false /*isParsingIntelSyntax()*/));
44570b57cec5SDimitry Andric         Op.setTokenValue(Base);
44580b57cec5SDimitry Andric       }
44590b57cec5SDimitry Andric     }
44600b57cec5SDimitry Andric   }
44610b57cec5SDimitry Andric 
44620b57cec5SDimitry Andric   // If an unsized memory operand is present, try to match with each memory
44630b57cec5SDimitry Andric   // operand size.  In Intel assembly, the size is not part of the instruction
44640b57cec5SDimitry Andric   // mnemonic.
44650b57cec5SDimitry Andric   if (UnsizedMemOp && UnsizedMemOp->isMemUnsized()) {
44660b57cec5SDimitry Andric     static const unsigned MopSizes[] = {8, 16, 32, 64, 80, 128, 256, 512};
44670b57cec5SDimitry Andric     for (unsigned Size : MopSizes) {
44680b57cec5SDimitry Andric       UnsizedMemOp->Mem.Size = Size;
44690b57cec5SDimitry Andric       uint64_t ErrorInfoIgnore;
44700b57cec5SDimitry Andric       unsigned LastOpcode = Inst.getOpcode();
44710b57cec5SDimitry Andric       unsigned M = MatchInstruction(Operands, Inst, ErrorInfoIgnore,
44720b57cec5SDimitry Andric                                     MissingFeatures, MatchingInlineAsm,
44730b57cec5SDimitry Andric                                     isParsingIntelSyntax());
44740b57cec5SDimitry Andric       if (Match.empty() || LastOpcode != Inst.getOpcode())
44750b57cec5SDimitry Andric         Match.push_back(M);
44760b57cec5SDimitry Andric 
44770b57cec5SDimitry Andric       // If this returned as a missing feature failure, remember that.
44780b57cec5SDimitry Andric       if (Match.back() == Match_MissingFeature)
44790b57cec5SDimitry Andric         ErrorInfoMissingFeatures = MissingFeatures;
44800b57cec5SDimitry Andric     }
44810b57cec5SDimitry Andric 
44820b57cec5SDimitry Andric     // Restore the size of the unsized memory operand if we modified it.
44830b57cec5SDimitry Andric     UnsizedMemOp->Mem.Size = 0;
44840b57cec5SDimitry Andric   }
44850b57cec5SDimitry Andric 
44860b57cec5SDimitry Andric   // If we haven't matched anything yet, this is not a basic integer or FPU
44870b57cec5SDimitry Andric   // operation.  There shouldn't be any ambiguity in our mnemonic table, so try
44880b57cec5SDimitry Andric   // matching with the unsized operand.
44890b57cec5SDimitry Andric   if (Match.empty()) {
44900b57cec5SDimitry Andric     Match.push_back(MatchInstruction(
44910b57cec5SDimitry Andric         Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm,
44920b57cec5SDimitry Andric         isParsingIntelSyntax()));
44930b57cec5SDimitry Andric     // If this returned as a missing feature failure, remember that.
44940b57cec5SDimitry Andric     if (Match.back() == Match_MissingFeature)
44950b57cec5SDimitry Andric       ErrorInfoMissingFeatures = MissingFeatures;
44960b57cec5SDimitry Andric   }
44970b57cec5SDimitry Andric 
44980b57cec5SDimitry Andric   // Restore the size of the unsized memory operand if we modified it.
44990b57cec5SDimitry Andric   if (UnsizedMemOp)
45000b57cec5SDimitry Andric     UnsizedMemOp->Mem.Size = 0;
45010b57cec5SDimitry Andric 
45020b57cec5SDimitry Andric   // If it's a bad mnemonic, all results will be the same.
45030b57cec5SDimitry Andric   if (Match.back() == Match_MnemonicFail) {
45040b57cec5SDimitry Andric     return Error(IDLoc, "invalid instruction mnemonic '" + Mnemonic + "'",
45050b57cec5SDimitry Andric                  Op.getLocRange(), MatchingInlineAsm);
45060b57cec5SDimitry Andric   }
45070b57cec5SDimitry Andric 
45080eae32dcSDimitry Andric   unsigned NumSuccessfulMatches = llvm::count(Match, Match_Success);
45090b57cec5SDimitry Andric 
45100b57cec5SDimitry Andric   // If matching was ambiguous and we had size information from the frontend,
45110b57cec5SDimitry Andric   // try again with that. This handles cases like "movxz eax, m8/m16".
45120b57cec5SDimitry Andric   if (UnsizedMemOp && NumSuccessfulMatches > 1 &&
45130b57cec5SDimitry Andric       UnsizedMemOp->getMemFrontendSize()) {
45140b57cec5SDimitry Andric     UnsizedMemOp->Mem.Size = UnsizedMemOp->getMemFrontendSize();
45150b57cec5SDimitry Andric     unsigned M = MatchInstruction(
45160b57cec5SDimitry Andric         Operands, Inst, ErrorInfo, MissingFeatures, MatchingInlineAsm,
45170b57cec5SDimitry Andric         isParsingIntelSyntax());
45180b57cec5SDimitry Andric     if (M == Match_Success)
45190b57cec5SDimitry Andric       NumSuccessfulMatches = 1;
45200b57cec5SDimitry Andric 
45210b57cec5SDimitry Andric     // Add a rewrite that encodes the size information we used from the
45220b57cec5SDimitry Andric     // frontend.
45230b57cec5SDimitry Andric     InstInfo->AsmRewrites->emplace_back(
45240b57cec5SDimitry Andric         AOK_SizeDirective, UnsizedMemOp->getStartLoc(),
45250b57cec5SDimitry Andric         /*Len=*/0, UnsizedMemOp->getMemFrontendSize());
45260b57cec5SDimitry Andric   }
45270b57cec5SDimitry Andric 
45280b57cec5SDimitry Andric   // If exactly one matched, then we treat that as a successful match (and the
45290b57cec5SDimitry Andric   // instruction will already have been filled in correctly, since the failing
45300b57cec5SDimitry Andric   // matches won't have modified it).
45310b57cec5SDimitry Andric   if (NumSuccessfulMatches == 1) {
45320b57cec5SDimitry Andric     if (!MatchingInlineAsm && validateInstruction(Inst, Operands))
45330b57cec5SDimitry Andric       return true;
45340b57cec5SDimitry Andric     // Some instructions need post-processing to, for example, tweak which
45350b57cec5SDimitry Andric     // encoding is selected. Loop on it while changes happen so the individual
45360b57cec5SDimitry Andric     // transformations can chain off each other.
45370b57cec5SDimitry Andric     if (!MatchingInlineAsm)
45380b57cec5SDimitry Andric       while (processInstruction(Inst, Operands))
45390b57cec5SDimitry Andric         ;
45400b57cec5SDimitry Andric     Inst.setLoc(IDLoc);
45410b57cec5SDimitry Andric     if (!MatchingInlineAsm)
45425ffd83dbSDimitry Andric       emitInstruction(Inst, Operands, Out);
45430b57cec5SDimitry Andric     Opcode = Inst.getOpcode();
45440b57cec5SDimitry Andric     return false;
45450b57cec5SDimitry Andric   } else if (NumSuccessfulMatches > 1) {
45460b57cec5SDimitry Andric     assert(UnsizedMemOp &&
45470b57cec5SDimitry Andric            "multiple matches only possible with unsized memory operands");
45480b57cec5SDimitry Andric     return Error(UnsizedMemOp->getStartLoc(),
45490b57cec5SDimitry Andric                  "ambiguous operand size for instruction '" + Mnemonic + "\'",
45500b57cec5SDimitry Andric                  UnsizedMemOp->getLocRange());
45510b57cec5SDimitry Andric   }
45520b57cec5SDimitry Andric 
45530b57cec5SDimitry Andric   // If one instruction matched as unsupported, report this as unsupported.
45540eae32dcSDimitry Andric   if (llvm::count(Match, Match_Unsupported) == 1) {
45550b57cec5SDimitry Andric     return Error(IDLoc, "unsupported instruction", EmptyRange,
45560b57cec5SDimitry Andric                  MatchingInlineAsm);
45570b57cec5SDimitry Andric   }
45580b57cec5SDimitry Andric 
45590b57cec5SDimitry Andric   // If one instruction matched with a missing feature, report this as a
45600b57cec5SDimitry Andric   // missing feature.
45610eae32dcSDimitry Andric   if (llvm::count(Match, Match_MissingFeature) == 1) {
45620b57cec5SDimitry Andric     ErrorInfo = Match_MissingFeature;
45630b57cec5SDimitry Andric     return ErrorMissingFeature(IDLoc, ErrorInfoMissingFeatures,
45640b57cec5SDimitry Andric                                MatchingInlineAsm);
45650b57cec5SDimitry Andric   }
45660b57cec5SDimitry Andric 
45670b57cec5SDimitry Andric   // If one instruction matched with an invalid operand, report this as an
45680b57cec5SDimitry Andric   // operand failure.
45690eae32dcSDimitry Andric   if (llvm::count(Match, Match_InvalidOperand) == 1) {
45700b57cec5SDimitry Andric     return Error(IDLoc, "invalid operand for instruction", EmptyRange,
45710b57cec5SDimitry Andric                  MatchingInlineAsm);
45720b57cec5SDimitry Andric   }
45730b57cec5SDimitry Andric 
45740eae32dcSDimitry Andric   if (llvm::count(Match, Match_InvalidImmUnsignedi4) == 1) {
45758bcb0991SDimitry Andric     SMLoc ErrorLoc = ((X86Operand &)*Operands[ErrorInfo]).getStartLoc();
45768bcb0991SDimitry Andric     if (ErrorLoc == SMLoc())
45778bcb0991SDimitry Andric       ErrorLoc = IDLoc;
45788bcb0991SDimitry Andric     return Error(ErrorLoc, "immediate must be an integer in range [0, 15]",
45798bcb0991SDimitry Andric                  EmptyRange, MatchingInlineAsm);
45808bcb0991SDimitry Andric   }
45818bcb0991SDimitry Andric 
45820b57cec5SDimitry Andric   // If all of these were an outright failure, report it in a useless way.
45830b57cec5SDimitry Andric   return Error(IDLoc, "unknown instruction mnemonic", EmptyRange,
45840b57cec5SDimitry Andric                MatchingInlineAsm);
45850b57cec5SDimitry Andric }
45860b57cec5SDimitry Andric 
OmitRegisterFromClobberLists(unsigned RegNo)45870b57cec5SDimitry Andric bool X86AsmParser::OmitRegisterFromClobberLists(unsigned RegNo) {
45880b57cec5SDimitry Andric   return X86MCRegisterClasses[X86::SEGMENT_REGRegClassID].contains(RegNo);
45890b57cec5SDimitry Andric }
45900b57cec5SDimitry Andric 
ParseDirective(AsmToken DirectiveID)45910b57cec5SDimitry Andric bool X86AsmParser::ParseDirective(AsmToken DirectiveID) {
45920b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
45930b57cec5SDimitry Andric   StringRef IDVal = DirectiveID.getIdentifier();
45945f757f3fSDimitry Andric   if (IDVal.starts_with(".arch"))
4595e8d8bef9SDimitry Andric     return parseDirectiveArch();
45965f757f3fSDimitry Andric   if (IDVal.starts_with(".code"))
45970b57cec5SDimitry Andric     return ParseDirectiveCode(IDVal, DirectiveID.getLoc());
45985f757f3fSDimitry Andric   else if (IDVal.starts_with(".att_syntax")) {
45990b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
46000b57cec5SDimitry Andric       if (Parser.getTok().getString() == "prefix")
46010b57cec5SDimitry Andric         Parser.Lex();
46020b57cec5SDimitry Andric       else if (Parser.getTok().getString() == "noprefix")
46030b57cec5SDimitry Andric         return Error(DirectiveID.getLoc(), "'.att_syntax noprefix' is not "
46040b57cec5SDimitry Andric                                            "supported: registers must have a "
46050b57cec5SDimitry Andric                                            "'%' prefix in .att_syntax");
46060b57cec5SDimitry Andric     }
46070b57cec5SDimitry Andric     getParser().setAssemblerDialect(0);
46080b57cec5SDimitry Andric     return false;
46095f757f3fSDimitry Andric   } else if (IDVal.starts_with(".intel_syntax")) {
46100b57cec5SDimitry Andric     getParser().setAssemblerDialect(1);
46110b57cec5SDimitry Andric     if (getLexer().isNot(AsmToken::EndOfStatement)) {
46120b57cec5SDimitry Andric       if (Parser.getTok().getString() == "noprefix")
46130b57cec5SDimitry Andric         Parser.Lex();
46140b57cec5SDimitry Andric       else if (Parser.getTok().getString() == "prefix")
46150b57cec5SDimitry Andric         return Error(DirectiveID.getLoc(), "'.intel_syntax prefix' is not "
46160b57cec5SDimitry Andric                                            "supported: registers must not have "
46170b57cec5SDimitry Andric                                            "a '%' prefix in .intel_syntax");
46180b57cec5SDimitry Andric     }
46190b57cec5SDimitry Andric     return false;
4620e8d8bef9SDimitry Andric   } else if (IDVal == ".nops")
4621e8d8bef9SDimitry Andric     return parseDirectiveNops(DirectiveID.getLoc());
4622e8d8bef9SDimitry Andric   else if (IDVal == ".even")
46230b57cec5SDimitry Andric     return parseDirectiveEven(DirectiveID.getLoc());
46240b57cec5SDimitry Andric   else if (IDVal == ".cv_fpo_proc")
46250b57cec5SDimitry Andric     return parseDirectiveFPOProc(DirectiveID.getLoc());
46260b57cec5SDimitry Andric   else if (IDVal == ".cv_fpo_setframe")
46270b57cec5SDimitry Andric     return parseDirectiveFPOSetFrame(DirectiveID.getLoc());
46280b57cec5SDimitry Andric   else if (IDVal == ".cv_fpo_pushreg")
46290b57cec5SDimitry Andric     return parseDirectiveFPOPushReg(DirectiveID.getLoc());
46300b57cec5SDimitry Andric   else if (IDVal == ".cv_fpo_stackalloc")
46310b57cec5SDimitry Andric     return parseDirectiveFPOStackAlloc(DirectiveID.getLoc());
46320b57cec5SDimitry Andric   else if (IDVal == ".cv_fpo_stackalign")
46330b57cec5SDimitry Andric     return parseDirectiveFPOStackAlign(DirectiveID.getLoc());
46340b57cec5SDimitry Andric   else if (IDVal == ".cv_fpo_endprologue")
46350b57cec5SDimitry Andric     return parseDirectiveFPOEndPrologue(DirectiveID.getLoc());
46360b57cec5SDimitry Andric   else if (IDVal == ".cv_fpo_endproc")
46370b57cec5SDimitry Andric     return parseDirectiveFPOEndProc(DirectiveID.getLoc());
4638e8d8bef9SDimitry Andric   else if (IDVal == ".seh_pushreg" ||
4639fe6060f1SDimitry Andric            (Parser.isParsingMasm() && IDVal.equals_insensitive(".pushreg")))
46408bcb0991SDimitry Andric     return parseDirectiveSEHPushReg(DirectiveID.getLoc());
4641e8d8bef9SDimitry Andric   else if (IDVal == ".seh_setframe" ||
4642fe6060f1SDimitry Andric            (Parser.isParsingMasm() && IDVal.equals_insensitive(".setframe")))
46438bcb0991SDimitry Andric     return parseDirectiveSEHSetFrame(DirectiveID.getLoc());
4644e8d8bef9SDimitry Andric   else if (IDVal == ".seh_savereg" ||
4645fe6060f1SDimitry Andric            (Parser.isParsingMasm() && IDVal.equals_insensitive(".savereg")))
46468bcb0991SDimitry Andric     return parseDirectiveSEHSaveReg(DirectiveID.getLoc());
4647e8d8bef9SDimitry Andric   else if (IDVal == ".seh_savexmm" ||
4648fe6060f1SDimitry Andric            (Parser.isParsingMasm() && IDVal.equals_insensitive(".savexmm128")))
46498bcb0991SDimitry Andric     return parseDirectiveSEHSaveXMM(DirectiveID.getLoc());
4650e8d8bef9SDimitry Andric   else if (IDVal == ".seh_pushframe" ||
4651fe6060f1SDimitry Andric            (Parser.isParsingMasm() && IDVal.equals_insensitive(".pushframe")))
46528bcb0991SDimitry Andric     return parseDirectiveSEHPushFrame(DirectiveID.getLoc());
46530b57cec5SDimitry Andric 
46540b57cec5SDimitry Andric   return true;
46550b57cec5SDimitry Andric }
46560b57cec5SDimitry Andric 
parseDirectiveArch()4657e8d8bef9SDimitry Andric bool X86AsmParser::parseDirectiveArch() {
4658e8d8bef9SDimitry Andric   // Ignore .arch for now.
4659e8d8bef9SDimitry Andric   getParser().parseStringToEndOfStatement();
4660e8d8bef9SDimitry Andric   return false;
4661e8d8bef9SDimitry Andric }
4662e8d8bef9SDimitry Andric 
4663e8d8bef9SDimitry Andric /// parseDirectiveNops
4664e8d8bef9SDimitry Andric ///  ::= .nops size[, control]
parseDirectiveNops(SMLoc L)4665e8d8bef9SDimitry Andric bool X86AsmParser::parseDirectiveNops(SMLoc L) {
4666e8d8bef9SDimitry Andric   int64_t NumBytes = 0, Control = 0;
4667e8d8bef9SDimitry Andric   SMLoc NumBytesLoc, ControlLoc;
4668349cc55cSDimitry Andric   const MCSubtargetInfo& STI = getSTI();
4669e8d8bef9SDimitry Andric   NumBytesLoc = getTok().getLoc();
4670e8d8bef9SDimitry Andric   if (getParser().checkForValidSection() ||
4671e8d8bef9SDimitry Andric       getParser().parseAbsoluteExpression(NumBytes))
4672e8d8bef9SDimitry Andric     return true;
4673e8d8bef9SDimitry Andric 
4674e8d8bef9SDimitry Andric   if (parseOptionalToken(AsmToken::Comma)) {
4675e8d8bef9SDimitry Andric     ControlLoc = getTok().getLoc();
4676e8d8bef9SDimitry Andric     if (getParser().parseAbsoluteExpression(Control))
4677e8d8bef9SDimitry Andric       return true;
4678e8d8bef9SDimitry Andric   }
467981ad6265SDimitry Andric   if (getParser().parseEOL())
4680e8d8bef9SDimitry Andric     return true;
4681e8d8bef9SDimitry Andric 
4682e8d8bef9SDimitry Andric   if (NumBytes <= 0) {
4683e8d8bef9SDimitry Andric     Error(NumBytesLoc, "'.nops' directive with non-positive size");
4684e8d8bef9SDimitry Andric     return false;
4685e8d8bef9SDimitry Andric   }
4686e8d8bef9SDimitry Andric 
4687e8d8bef9SDimitry Andric   if (Control < 0) {
4688e8d8bef9SDimitry Andric     Error(ControlLoc, "'.nops' directive with negative NOP size");
4689e8d8bef9SDimitry Andric     return false;
4690e8d8bef9SDimitry Andric   }
4691e8d8bef9SDimitry Andric 
4692e8d8bef9SDimitry Andric   /// Emit nops
4693349cc55cSDimitry Andric   getParser().getStreamer().emitNops(NumBytes, Control, L, STI);
4694e8d8bef9SDimitry Andric 
4695e8d8bef9SDimitry Andric   return false;
4696e8d8bef9SDimitry Andric }
4697e8d8bef9SDimitry Andric 
46980b57cec5SDimitry Andric /// parseDirectiveEven
46990b57cec5SDimitry Andric ///  ::= .even
parseDirectiveEven(SMLoc L)47000b57cec5SDimitry Andric bool X86AsmParser::parseDirectiveEven(SMLoc L) {
470181ad6265SDimitry Andric   if (parseEOL())
47020b57cec5SDimitry Andric     return false;
47030b57cec5SDimitry Andric 
47040b57cec5SDimitry Andric   const MCSection *Section = getStreamer().getCurrentSectionOnly();
47050b57cec5SDimitry Andric   if (!Section) {
4706349cc55cSDimitry Andric     getStreamer().initSections(false, getSTI());
47070b57cec5SDimitry Andric     Section = getStreamer().getCurrentSectionOnly();
47080b57cec5SDimitry Andric   }
470981ad6265SDimitry Andric   if (Section->useCodeAlign())
4710bdd1243dSDimitry Andric     getStreamer().emitCodeAlignment(Align(2), &getSTI(), 0);
47110b57cec5SDimitry Andric   else
4712bdd1243dSDimitry Andric     getStreamer().emitValueToAlignment(Align(2), 0, 1, 0);
47130b57cec5SDimitry Andric   return false;
47140b57cec5SDimitry Andric }
47150b57cec5SDimitry Andric 
47160b57cec5SDimitry Andric /// ParseDirectiveCode
47170b57cec5SDimitry Andric ///  ::= .code16 | .code32 | .code64
ParseDirectiveCode(StringRef IDVal,SMLoc L)47180b57cec5SDimitry Andric bool X86AsmParser::ParseDirectiveCode(StringRef IDVal, SMLoc L) {
47190b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
47200b57cec5SDimitry Andric   Code16GCC = false;
47210b57cec5SDimitry Andric   if (IDVal == ".code16") {
47220b57cec5SDimitry Andric     Parser.Lex();
47230b57cec5SDimitry Andric     if (!is16BitMode()) {
472481ad6265SDimitry Andric       SwitchMode(X86::Is16Bit);
47255ffd83dbSDimitry Andric       getParser().getStreamer().emitAssemblerFlag(MCAF_Code16);
47260b57cec5SDimitry Andric     }
47270b57cec5SDimitry Andric   } else if (IDVal == ".code16gcc") {
47280b57cec5SDimitry Andric     // .code16gcc parses as if in 32-bit mode, but emits code in 16-bit mode.
47290b57cec5SDimitry Andric     Parser.Lex();
47300b57cec5SDimitry Andric     Code16GCC = true;
47310b57cec5SDimitry Andric     if (!is16BitMode()) {
473281ad6265SDimitry Andric       SwitchMode(X86::Is16Bit);
47335ffd83dbSDimitry Andric       getParser().getStreamer().emitAssemblerFlag(MCAF_Code16);
47340b57cec5SDimitry Andric     }
47350b57cec5SDimitry Andric   } else if (IDVal == ".code32") {
47360b57cec5SDimitry Andric     Parser.Lex();
47370b57cec5SDimitry Andric     if (!is32BitMode()) {
473881ad6265SDimitry Andric       SwitchMode(X86::Is32Bit);
47395ffd83dbSDimitry Andric       getParser().getStreamer().emitAssemblerFlag(MCAF_Code32);
47400b57cec5SDimitry Andric     }
47410b57cec5SDimitry Andric   } else if (IDVal == ".code64") {
47420b57cec5SDimitry Andric     Parser.Lex();
47430b57cec5SDimitry Andric     if (!is64BitMode()) {
474481ad6265SDimitry Andric       SwitchMode(X86::Is64Bit);
47455ffd83dbSDimitry Andric       getParser().getStreamer().emitAssemblerFlag(MCAF_Code64);
47460b57cec5SDimitry Andric     }
47470b57cec5SDimitry Andric   } else {
47480b57cec5SDimitry Andric     Error(L, "unknown directive " + IDVal);
47490b57cec5SDimitry Andric     return false;
47500b57cec5SDimitry Andric   }
47510b57cec5SDimitry Andric 
47520b57cec5SDimitry Andric   return false;
47530b57cec5SDimitry Andric }
47540b57cec5SDimitry Andric 
47550b57cec5SDimitry Andric // .cv_fpo_proc foo
parseDirectiveFPOProc(SMLoc L)47560b57cec5SDimitry Andric bool X86AsmParser::parseDirectiveFPOProc(SMLoc L) {
47570b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
47580b57cec5SDimitry Andric   StringRef ProcName;
47590b57cec5SDimitry Andric   int64_t ParamsSize;
47600b57cec5SDimitry Andric   if (Parser.parseIdentifier(ProcName))
47610b57cec5SDimitry Andric     return Parser.TokError("expected symbol name");
47620b57cec5SDimitry Andric   if (Parser.parseIntToken(ParamsSize, "expected parameter byte count"))
47630b57cec5SDimitry Andric     return true;
47640b57cec5SDimitry Andric   if (!isUIntN(32, ParamsSize))
47650b57cec5SDimitry Andric     return Parser.TokError("parameters size out of range");
4766fe6060f1SDimitry Andric   if (parseEOL())
4767fe6060f1SDimitry Andric     return true;
47680b57cec5SDimitry Andric   MCSymbol *ProcSym = getContext().getOrCreateSymbol(ProcName);
47690b57cec5SDimitry Andric   return getTargetStreamer().emitFPOProc(ProcSym, ParamsSize, L);
47700b57cec5SDimitry Andric }
47710b57cec5SDimitry Andric 
47720b57cec5SDimitry Andric // .cv_fpo_setframe ebp
parseDirectiveFPOSetFrame(SMLoc L)47730b57cec5SDimitry Andric bool X86AsmParser::parseDirectiveFPOSetFrame(SMLoc L) {
4774bdd1243dSDimitry Andric   MCRegister Reg;
47750b57cec5SDimitry Andric   SMLoc DummyLoc;
4776bdd1243dSDimitry Andric   if (parseRegister(Reg, DummyLoc, DummyLoc) || parseEOL())
4777fe6060f1SDimitry Andric     return true;
47780b57cec5SDimitry Andric   return getTargetStreamer().emitFPOSetFrame(Reg, L);
47790b57cec5SDimitry Andric }
47800b57cec5SDimitry Andric 
47810b57cec5SDimitry Andric // .cv_fpo_pushreg ebx
parseDirectiveFPOPushReg(SMLoc L)47820b57cec5SDimitry Andric bool X86AsmParser::parseDirectiveFPOPushReg(SMLoc L) {
4783bdd1243dSDimitry Andric   MCRegister Reg;
47840b57cec5SDimitry Andric   SMLoc DummyLoc;
4785bdd1243dSDimitry Andric   if (parseRegister(Reg, DummyLoc, DummyLoc) || parseEOL())
4786fe6060f1SDimitry Andric     return true;
47870b57cec5SDimitry Andric   return getTargetStreamer().emitFPOPushReg(Reg, L);
47880b57cec5SDimitry Andric }
47890b57cec5SDimitry Andric 
47900b57cec5SDimitry Andric // .cv_fpo_stackalloc 20
parseDirectiveFPOStackAlloc(SMLoc L)47910b57cec5SDimitry Andric bool X86AsmParser::parseDirectiveFPOStackAlloc(SMLoc L) {
47920b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
47930b57cec5SDimitry Andric   int64_t Offset;
4794fe6060f1SDimitry Andric   if (Parser.parseIntToken(Offset, "expected offset") || parseEOL())
4795fe6060f1SDimitry Andric     return true;
47960b57cec5SDimitry Andric   return getTargetStreamer().emitFPOStackAlloc(Offset, L);
47970b57cec5SDimitry Andric }
47980b57cec5SDimitry Andric 
47990b57cec5SDimitry Andric // .cv_fpo_stackalign 8
parseDirectiveFPOStackAlign(SMLoc L)48000b57cec5SDimitry Andric bool X86AsmParser::parseDirectiveFPOStackAlign(SMLoc L) {
48010b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
48020b57cec5SDimitry Andric   int64_t Offset;
4803fe6060f1SDimitry Andric   if (Parser.parseIntToken(Offset, "expected offset") || parseEOL())
4804fe6060f1SDimitry Andric     return true;
48050b57cec5SDimitry Andric   return getTargetStreamer().emitFPOStackAlign(Offset, L);
48060b57cec5SDimitry Andric }
48070b57cec5SDimitry Andric 
48080b57cec5SDimitry Andric // .cv_fpo_endprologue
parseDirectiveFPOEndPrologue(SMLoc L)48090b57cec5SDimitry Andric bool X86AsmParser::parseDirectiveFPOEndPrologue(SMLoc L) {
48100b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
4811fe6060f1SDimitry Andric   if (Parser.parseEOL())
4812fe6060f1SDimitry Andric     return true;
48130b57cec5SDimitry Andric   return getTargetStreamer().emitFPOEndPrologue(L);
48140b57cec5SDimitry Andric }
48150b57cec5SDimitry Andric 
48160b57cec5SDimitry Andric // .cv_fpo_endproc
parseDirectiveFPOEndProc(SMLoc L)48170b57cec5SDimitry Andric bool X86AsmParser::parseDirectiveFPOEndProc(SMLoc L) {
48180b57cec5SDimitry Andric   MCAsmParser &Parser = getParser();
4819fe6060f1SDimitry Andric   if (Parser.parseEOL())
4820fe6060f1SDimitry Andric     return true;
48210b57cec5SDimitry Andric   return getTargetStreamer().emitFPOEndProc(L);
48220b57cec5SDimitry Andric }
48230b57cec5SDimitry Andric 
parseSEHRegisterNumber(unsigned RegClassID,MCRegister & RegNo)48248bcb0991SDimitry Andric bool X86AsmParser::parseSEHRegisterNumber(unsigned RegClassID,
4825bdd1243dSDimitry Andric                                           MCRegister &RegNo) {
48268bcb0991SDimitry Andric   SMLoc startLoc = getLexer().getLoc();
48278bcb0991SDimitry Andric   const MCRegisterInfo *MRI = getContext().getRegisterInfo();
48288bcb0991SDimitry Andric 
48298bcb0991SDimitry Andric   // Try parsing the argument as a register first.
48308bcb0991SDimitry Andric   if (getLexer().getTok().isNot(AsmToken::Integer)) {
48318bcb0991SDimitry Andric     SMLoc endLoc;
4832bdd1243dSDimitry Andric     if (parseRegister(RegNo, startLoc, endLoc))
48338bcb0991SDimitry Andric       return true;
48348bcb0991SDimitry Andric 
48358bcb0991SDimitry Andric     if (!X86MCRegisterClasses[RegClassID].contains(RegNo)) {
48368bcb0991SDimitry Andric       return Error(startLoc,
48378bcb0991SDimitry Andric                    "register is not supported for use with this directive");
48388bcb0991SDimitry Andric     }
48398bcb0991SDimitry Andric   } else {
48408bcb0991SDimitry Andric     // Otherwise, an integer number matching the encoding of the desired
48418bcb0991SDimitry Andric     // register may appear.
48428bcb0991SDimitry Andric     int64_t EncodedReg;
48438bcb0991SDimitry Andric     if (getParser().parseAbsoluteExpression(EncodedReg))
48448bcb0991SDimitry Andric       return true;
48458bcb0991SDimitry Andric 
48468bcb0991SDimitry Andric     // The SEH register number is the same as the encoding register number. Map
48478bcb0991SDimitry Andric     // from the encoding back to the LLVM register number.
48488bcb0991SDimitry Andric     RegNo = 0;
48498bcb0991SDimitry Andric     for (MCPhysReg Reg : X86MCRegisterClasses[RegClassID]) {
48508bcb0991SDimitry Andric       if (MRI->getEncodingValue(Reg) == EncodedReg) {
48518bcb0991SDimitry Andric         RegNo = Reg;
48528bcb0991SDimitry Andric         break;
48538bcb0991SDimitry Andric       }
48548bcb0991SDimitry Andric     }
48558bcb0991SDimitry Andric     if (RegNo == 0) {
48568bcb0991SDimitry Andric       return Error(startLoc,
48578bcb0991SDimitry Andric                    "incorrect register number for use with this directive");
48588bcb0991SDimitry Andric     }
48598bcb0991SDimitry Andric   }
48608bcb0991SDimitry Andric 
48618bcb0991SDimitry Andric   return false;
48628bcb0991SDimitry Andric }
48638bcb0991SDimitry Andric 
parseDirectiveSEHPushReg(SMLoc Loc)48648bcb0991SDimitry Andric bool X86AsmParser::parseDirectiveSEHPushReg(SMLoc Loc) {
4865bdd1243dSDimitry Andric   MCRegister Reg;
48668bcb0991SDimitry Andric   if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
48678bcb0991SDimitry Andric     return true;
48688bcb0991SDimitry Andric 
48698bcb0991SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
4870bdd1243dSDimitry Andric     return TokError("expected end of directive");
48718bcb0991SDimitry Andric 
48728bcb0991SDimitry Andric   getParser().Lex();
487381ad6265SDimitry Andric   getStreamer().emitWinCFIPushReg(Reg, Loc);
48748bcb0991SDimitry Andric   return false;
48758bcb0991SDimitry Andric }
48768bcb0991SDimitry Andric 
parseDirectiveSEHSetFrame(SMLoc Loc)48778bcb0991SDimitry Andric bool X86AsmParser::parseDirectiveSEHSetFrame(SMLoc Loc) {
4878bdd1243dSDimitry Andric   MCRegister Reg;
48798bcb0991SDimitry Andric   int64_t Off;
48808bcb0991SDimitry Andric   if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
48818bcb0991SDimitry Andric     return true;
48828bcb0991SDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
48838bcb0991SDimitry Andric     return TokError("you must specify a stack pointer offset");
48848bcb0991SDimitry Andric 
48858bcb0991SDimitry Andric   getParser().Lex();
48868bcb0991SDimitry Andric   if (getParser().parseAbsoluteExpression(Off))
48878bcb0991SDimitry Andric     return true;
48888bcb0991SDimitry Andric 
48898bcb0991SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
4890bdd1243dSDimitry Andric     return TokError("expected end of directive");
48918bcb0991SDimitry Andric 
48928bcb0991SDimitry Andric   getParser().Lex();
489381ad6265SDimitry Andric   getStreamer().emitWinCFISetFrame(Reg, Off, Loc);
48948bcb0991SDimitry Andric   return false;
48958bcb0991SDimitry Andric }
48968bcb0991SDimitry Andric 
parseDirectiveSEHSaveReg(SMLoc Loc)48978bcb0991SDimitry Andric bool X86AsmParser::parseDirectiveSEHSaveReg(SMLoc Loc) {
4898bdd1243dSDimitry Andric   MCRegister Reg;
48998bcb0991SDimitry Andric   int64_t Off;
49008bcb0991SDimitry Andric   if (parseSEHRegisterNumber(X86::GR64RegClassID, Reg))
49018bcb0991SDimitry Andric     return true;
49028bcb0991SDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
49038bcb0991SDimitry Andric     return TokError("you must specify an offset on the stack");
49048bcb0991SDimitry Andric 
49058bcb0991SDimitry Andric   getParser().Lex();
49068bcb0991SDimitry Andric   if (getParser().parseAbsoluteExpression(Off))
49078bcb0991SDimitry Andric     return true;
49088bcb0991SDimitry Andric 
49098bcb0991SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
4910bdd1243dSDimitry Andric     return TokError("expected end of directive");
49118bcb0991SDimitry Andric 
49128bcb0991SDimitry Andric   getParser().Lex();
491381ad6265SDimitry Andric   getStreamer().emitWinCFISaveReg(Reg, Off, Loc);
49148bcb0991SDimitry Andric   return false;
49158bcb0991SDimitry Andric }
49168bcb0991SDimitry Andric 
parseDirectiveSEHSaveXMM(SMLoc Loc)49178bcb0991SDimitry Andric bool X86AsmParser::parseDirectiveSEHSaveXMM(SMLoc Loc) {
4918bdd1243dSDimitry Andric   MCRegister Reg;
49198bcb0991SDimitry Andric   int64_t Off;
49208bcb0991SDimitry Andric   if (parseSEHRegisterNumber(X86::VR128XRegClassID, Reg))
49218bcb0991SDimitry Andric     return true;
49228bcb0991SDimitry Andric   if (getLexer().isNot(AsmToken::Comma))
49238bcb0991SDimitry Andric     return TokError("you must specify an offset on the stack");
49248bcb0991SDimitry Andric 
49258bcb0991SDimitry Andric   getParser().Lex();
49268bcb0991SDimitry Andric   if (getParser().parseAbsoluteExpression(Off))
49278bcb0991SDimitry Andric     return true;
49288bcb0991SDimitry Andric 
49298bcb0991SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
4930bdd1243dSDimitry Andric     return TokError("expected end of directive");
49318bcb0991SDimitry Andric 
49328bcb0991SDimitry Andric   getParser().Lex();
493381ad6265SDimitry Andric   getStreamer().emitWinCFISaveXMM(Reg, Off, Loc);
49348bcb0991SDimitry Andric   return false;
49358bcb0991SDimitry Andric }
49368bcb0991SDimitry Andric 
parseDirectiveSEHPushFrame(SMLoc Loc)49378bcb0991SDimitry Andric bool X86AsmParser::parseDirectiveSEHPushFrame(SMLoc Loc) {
49388bcb0991SDimitry Andric   bool Code = false;
49398bcb0991SDimitry Andric   StringRef CodeID;
49408bcb0991SDimitry Andric   if (getLexer().is(AsmToken::At)) {
49418bcb0991SDimitry Andric     SMLoc startLoc = getLexer().getLoc();
49428bcb0991SDimitry Andric     getParser().Lex();
49438bcb0991SDimitry Andric     if (!getParser().parseIdentifier(CodeID)) {
49448bcb0991SDimitry Andric       if (CodeID != "code")
49458bcb0991SDimitry Andric         return Error(startLoc, "expected @code");
49468bcb0991SDimitry Andric       Code = true;
49478bcb0991SDimitry Andric     }
49488bcb0991SDimitry Andric   }
49498bcb0991SDimitry Andric 
49508bcb0991SDimitry Andric   if (getLexer().isNot(AsmToken::EndOfStatement))
4951bdd1243dSDimitry Andric     return TokError("expected end of directive");
49528bcb0991SDimitry Andric 
49538bcb0991SDimitry Andric   getParser().Lex();
495481ad6265SDimitry Andric   getStreamer().emitWinCFIPushFrame(Code, Loc);
49558bcb0991SDimitry Andric   return false;
49568bcb0991SDimitry Andric }
49578bcb0991SDimitry Andric 
49580b57cec5SDimitry Andric // Force static initialization.
LLVMInitializeX86AsmParser()4959480093f4SDimitry Andric extern "C" LLVM_EXTERNAL_VISIBILITY void LLVMInitializeX86AsmParser() {
49600b57cec5SDimitry Andric   RegisterMCAsmParser<X86AsmParser> X(getTheX86_32Target());
49610b57cec5SDimitry Andric   RegisterMCAsmParser<X86AsmParser> Y(getTheX86_64Target());
49620b57cec5SDimitry Andric }
49630b57cec5SDimitry Andric 
49640b57cec5SDimitry Andric #define GET_MATCHER_IMPLEMENTATION
49650b57cec5SDimitry Andric #include "X86GenAsmMatcher.inc"
4966