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