679 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
			
		
		
	
	
			679 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C++
		
	
	
	
| //===- X86Operand.h - Parsed X86 machine instruction ------------*- C++ -*-===//
 | |
| //
 | |
| // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
 | |
| // See https://llvm.org/LICENSE.txt for license information.
 | |
| // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
 | |
| //
 | |
| //===----------------------------------------------------------------------===//
 | |
| 
 | |
| #ifndef LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
 | |
| #define LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
 | |
| 
 | |
| #include "MCTargetDesc/X86IntelInstPrinter.h"
 | |
| #include "MCTargetDesc/X86MCTargetDesc.h"
 | |
| #include "X86AsmParserCommon.h"
 | |
| #include "llvm/ADT/STLExtras.h"
 | |
| #include "llvm/ADT/StringRef.h"
 | |
| #include "llvm/MC/MCExpr.h"
 | |
| #include "llvm/MC/MCInst.h"
 | |
| #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 | |
| #include "llvm/MC/MCRegisterInfo.h"
 | |
| #include "llvm/Support/Casting.h"
 | |
| #include "llvm/Support/ErrorHandling.h"
 | |
| #include "llvm/Support/SMLoc.h"
 | |
| #include <cassert>
 | |
| #include <memory>
 | |
| 
 | |
| namespace llvm {
 | |
| 
 | |
| /// X86Operand - Instances of this class represent a parsed X86 machine
 | |
| /// instruction.
 | |
| struct X86Operand final : public MCParsedAsmOperand {
 | |
|   enum KindTy { Token, Register, Immediate, Memory, Prefix, DXRegister } Kind;
 | |
| 
 | |
|   SMLoc StartLoc, EndLoc;
 | |
|   SMLoc OffsetOfLoc;
 | |
|   StringRef SymName;
 | |
|   void *OpDecl;
 | |
|   bool AddressOf;
 | |
|   bool CallOperand;
 | |
| 
 | |
|   struct TokOp {
 | |
|     const char *Data;
 | |
|     unsigned Length;
 | |
|   };
 | |
| 
 | |
|   struct RegOp {
 | |
|     unsigned RegNo;
 | |
|   };
 | |
| 
 | |
|   struct PrefOp {
 | |
|     unsigned Prefixes;
 | |
|   };
 | |
| 
 | |
|   struct ImmOp {
 | |
|     const MCExpr *Val;
 | |
|     bool LocalRef;
 | |
|   };
 | |
| 
 | |
|   struct MemOp {
 | |
|     unsigned SegReg;
 | |
|     const MCExpr *Disp;
 | |
|     unsigned BaseReg;
 | |
|     unsigned IndexReg;
 | |
|     unsigned Scale;
 | |
|     unsigned Size;
 | |
|     unsigned ModeSize;
 | |
| 
 | |
|     /// If the memory operand is unsized and there are multiple instruction
 | |
|     /// matches, prefer the one with this size.
 | |
|     unsigned FrontendSize;
 | |
|   };
 | |
| 
 | |
|   union {
 | |
|     struct TokOp Tok;
 | |
|     struct RegOp Reg;
 | |
|     struct ImmOp Imm;
 | |
|     struct MemOp Mem;
 | |
|     struct PrefOp Pref;
 | |
|   };
 | |
| 
 | |
|   X86Operand(KindTy K, SMLoc Start, SMLoc End)
 | |
|       : Kind(K), StartLoc(Start), EndLoc(End), CallOperand(false) {}
 | |
| 
 | |
|   StringRef getSymName() override { return SymName; }
 | |
|   void *getOpDecl() override { return OpDecl; }
 | |
| 
 | |
|   /// getStartLoc - Get the location of the first token of this operand.
 | |
|   SMLoc getStartLoc() const override { return StartLoc; }
 | |
| 
 | |
|   /// getEndLoc - Get the location of the last token of this operand.
 | |
|   SMLoc getEndLoc() const override { return EndLoc; }
 | |
| 
 | |
|   /// getLocRange - Get the range between the first and last token of this
 | |
|   /// operand.
 | |
|   SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
 | |
| 
 | |
|   /// getOffsetOfLoc - Get the location of the offset operator.
 | |
|   SMLoc getOffsetOfLoc() const override { return OffsetOfLoc; }
 | |
| 
 | |
|   void print(raw_ostream &OS) const override {
 | |
| 
 | |
|     auto PrintImmValue = [&](const MCExpr *Val, const char *VName) {
 | |
|       if (Val->getKind() == MCExpr::Constant) {
 | |
|         if (auto Imm = cast<MCConstantExpr>(Val)->getValue())
 | |
|           OS << VName << Imm;
 | |
|       } else if (Val->getKind() == MCExpr::SymbolRef) {
 | |
|         if (auto *SRE = dyn_cast<MCSymbolRefExpr>(Val)) {
 | |
|           const MCSymbol &Sym = SRE->getSymbol();
 | |
|           if (const char *SymNameStr = Sym.getName().data())
 | |
|             OS << VName << SymNameStr;
 | |
|         }
 | |
|       }
 | |
|     };
 | |
| 
 | |
|     switch (Kind) {
 | |
|     case Token:
 | |
|       OS << Tok.Data;
 | |
|       break;
 | |
|     case Register:
 | |
|       OS << "Reg:" << X86IntelInstPrinter::getRegisterName(Reg.RegNo);
 | |
|       break;
 | |
|     case DXRegister:
 | |
|       OS << "DXReg";
 | |
|       break;
 | |
|     case Immediate:
 | |
|       PrintImmValue(Imm.Val, "Imm:");
 | |
|       break;
 | |
|     case Prefix:
 | |
|       OS << "Prefix:" << Pref.Prefixes;
 | |
|       break;
 | |
|     case Memory:
 | |
|       OS << "Memory: ModeSize=" << Mem.ModeSize;
 | |
|       if (Mem.Size)
 | |
|         OS << ",Size=" << Mem.Size;
 | |
|       if (Mem.BaseReg)
 | |
|         OS << ",BaseReg=" << X86IntelInstPrinter::getRegisterName(Mem.BaseReg);
 | |
|       if (Mem.IndexReg)
 | |
|         OS << ",IndexReg="
 | |
|            << X86IntelInstPrinter::getRegisterName(Mem.IndexReg);
 | |
|       if (Mem.Scale)
 | |
|         OS << ",Scale=" << Mem.Scale;
 | |
|       if (Mem.Disp)
 | |
|         PrintImmValue(Mem.Disp, ",Disp=");
 | |
|       if (Mem.SegReg)
 | |
|         OS << ",SegReg=" << X86IntelInstPrinter::getRegisterName(Mem.SegReg);
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   StringRef getToken() const {
 | |
|     assert(Kind == Token && "Invalid access!");
 | |
|     return StringRef(Tok.Data, Tok.Length);
 | |
|   }
 | |
|   void setTokenValue(StringRef Value) {
 | |
|     assert(Kind == Token && "Invalid access!");
 | |
|     Tok.Data = Value.data();
 | |
|     Tok.Length = Value.size();
 | |
|   }
 | |
| 
 | |
|   unsigned getReg() const override {
 | |
|     assert(Kind == Register && "Invalid access!");
 | |
|     return Reg.RegNo;
 | |
|   }
 | |
| 
 | |
|   unsigned getPrefix() const {
 | |
|     assert(Kind == Prefix && "Invalid access!");
 | |
|     return Pref.Prefixes;
 | |
|   }
 | |
| 
 | |
|   const MCExpr *getImm() const {
 | |
|     assert(Kind == Immediate && "Invalid access!");
 | |
|     return Imm.Val;
 | |
|   }
 | |
| 
 | |
|   const MCExpr *getMemDisp() const {
 | |
|     assert(Kind == Memory && "Invalid access!");
 | |
|     return Mem.Disp;
 | |
|   }
 | |
|   unsigned getMemSegReg() const {
 | |
|     assert(Kind == Memory && "Invalid access!");
 | |
|     return Mem.SegReg;
 | |
|   }
 | |
|   unsigned getMemBaseReg() const {
 | |
|     assert(Kind == Memory && "Invalid access!");
 | |
|     return Mem.BaseReg;
 | |
|   }
 | |
|   unsigned getMemIndexReg() const {
 | |
|     assert(Kind == Memory && "Invalid access!");
 | |
|     return Mem.IndexReg;
 | |
|   }
 | |
|   unsigned getMemScale() const {
 | |
|     assert(Kind == Memory && "Invalid access!");
 | |
|     return Mem.Scale;
 | |
|   }
 | |
|   unsigned getMemModeSize() const {
 | |
|     assert(Kind == Memory && "Invalid access!");
 | |
|     return Mem.ModeSize;
 | |
|   }
 | |
|   unsigned getMemFrontendSize() const {
 | |
|     assert(Kind == Memory && "Invalid access!");
 | |
|     return Mem.FrontendSize;
 | |
|   }
 | |
| 
 | |
|   bool isToken() const override {return Kind == Token; }
 | |
| 
 | |
|   bool isImm() const override { return Kind == Immediate; }
 | |
| 
 | |
|   bool isImmSExti16i8() const {
 | |
|     if (!isImm())
 | |
|       return false;
 | |
| 
 | |
|     // If this isn't a constant expr, just assume it fits and let relaxation
 | |
|     // handle it.
 | |
|     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
 | |
|     if (!CE)
 | |
|       return true;
 | |
| 
 | |
|     // Otherwise, check the value is in a range that makes sense for this
 | |
|     // extension.
 | |
|     return isImmSExti16i8Value(CE->getValue());
 | |
|   }
 | |
|   bool isImmSExti32i8() const {
 | |
|     if (!isImm())
 | |
|       return false;
 | |
| 
 | |
|     // If this isn't a constant expr, just assume it fits and let relaxation
 | |
|     // handle it.
 | |
|     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
 | |
|     if (!CE)
 | |
|       return true;
 | |
| 
 | |
|     // Otherwise, check the value is in a range that makes sense for this
 | |
|     // extension.
 | |
|     return isImmSExti32i8Value(CE->getValue());
 | |
|   }
 | |
|   bool isImmSExti64i8() const {
 | |
|     if (!isImm())
 | |
|       return false;
 | |
| 
 | |
|     // If this isn't a constant expr, just assume it fits and let relaxation
 | |
|     // handle it.
 | |
|     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
 | |
|     if (!CE)
 | |
|       return true;
 | |
| 
 | |
|     // Otherwise, check the value is in a range that makes sense for this
 | |
|     // extension.
 | |
|     return isImmSExti64i8Value(CE->getValue());
 | |
|   }
 | |
|   bool isImmSExti64i32() const {
 | |
|     if (!isImm())
 | |
|       return false;
 | |
| 
 | |
|     // If this isn't a constant expr, just assume it fits and let relaxation
 | |
|     // handle it.
 | |
|     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
 | |
|     if (!CE)
 | |
|       return true;
 | |
| 
 | |
|     // Otherwise, check the value is in a range that makes sense for this
 | |
|     // extension.
 | |
|     return isImmSExti64i32Value(CE->getValue());
 | |
|   }
 | |
| 
 | |
|   bool isImmUnsignedi4() const {
 | |
|     if (!isImm()) return false;
 | |
|     // If this isn't a constant expr, reject it. The immediate byte is shared
 | |
|     // with a register encoding. We can't have it affected by a relocation.
 | |
|     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
 | |
|     if (!CE) return false;
 | |
|     return isImmUnsignedi4Value(CE->getValue());
 | |
|   }
 | |
| 
 | |
|   bool isImmUnsignedi8() const {
 | |
|     if (!isImm()) return false;
 | |
|     // If this isn't a constant expr, just assume it fits and let relaxation
 | |
|     // handle it.
 | |
|     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
 | |
|     if (!CE) return true;
 | |
|     return isImmUnsignedi8Value(CE->getValue());
 | |
|   }
 | |
| 
 | |
|   bool isOffsetOfLocal() const override { return isImm() && Imm.LocalRef; }
 | |
| 
 | |
|   bool needAddressOf() const override { return AddressOf; }
 | |
| 
 | |
|   bool isMem() const override { return Kind == Memory; }
 | |
|   bool isMemUnsized() const {
 | |
|     return Kind == Memory && Mem.Size == 0;
 | |
|   }
 | |
|   bool isMem8() const {
 | |
|     return Kind == Memory && (!Mem.Size || Mem.Size == 8);
 | |
|   }
 | |
|   bool isMem16() const {
 | |
|     return Kind == Memory && (!Mem.Size || Mem.Size == 16);
 | |
|   }
 | |
|   bool isMem32() const {
 | |
|     return Kind == Memory && (!Mem.Size || Mem.Size == 32);
 | |
|   }
 | |
|   bool isMem64() const {
 | |
|     return Kind == Memory && (!Mem.Size || Mem.Size == 64);
 | |
|   }
 | |
|   bool isMem80() const {
 | |
|     return Kind == Memory && (!Mem.Size || Mem.Size == 80);
 | |
|   }
 | |
|   bool isMem128() const {
 | |
|     return Kind == Memory && (!Mem.Size || Mem.Size == 128);
 | |
|   }
 | |
|   bool isMem256() const {
 | |
|     return Kind == Memory && (!Mem.Size || Mem.Size == 256);
 | |
|   }
 | |
|   bool isMem512() const {
 | |
|     return Kind == Memory && (!Mem.Size || Mem.Size == 512);
 | |
|   }
 | |
|   bool isMemIndexReg(unsigned LowR, unsigned HighR) const {
 | |
|     assert(Kind == Memory && "Invalid access!");
 | |
|     return Mem.IndexReg >= LowR && Mem.IndexReg <= HighR;
 | |
|   }
 | |
| 
 | |
|   bool isMem64_RC128() const {
 | |
|     return isMem64() && isMemIndexReg(X86::XMM0, X86::XMM15);
 | |
|   }
 | |
|   bool isMem128_RC128() const {
 | |
|     return isMem128() && isMemIndexReg(X86::XMM0, X86::XMM15);
 | |
|   }
 | |
|   bool isMem128_RC256() const {
 | |
|     return isMem128() && isMemIndexReg(X86::YMM0, X86::YMM15);
 | |
|   }
 | |
|   bool isMem256_RC128() const {
 | |
|     return isMem256() && isMemIndexReg(X86::XMM0, X86::XMM15);
 | |
|   }
 | |
|   bool isMem256_RC256() const {
 | |
|     return isMem256() && isMemIndexReg(X86::YMM0, X86::YMM15);
 | |
|   }
 | |
| 
 | |
|   bool isMem64_RC128X() const {
 | |
|     return isMem64() && isMemIndexReg(X86::XMM0, X86::XMM31);
 | |
|   }
 | |
|   bool isMem128_RC128X() const {
 | |
|     return isMem128() && isMemIndexReg(X86::XMM0, X86::XMM31);
 | |
|   }
 | |
|   bool isMem128_RC256X() const {
 | |
|     return isMem128() && isMemIndexReg(X86::YMM0, X86::YMM31);
 | |
|   }
 | |
|   bool isMem256_RC128X() const {
 | |
|     return isMem256() && isMemIndexReg(X86::XMM0, X86::XMM31);
 | |
|   }
 | |
|   bool isMem256_RC256X() const {
 | |
|     return isMem256() && isMemIndexReg(X86::YMM0, X86::YMM31);
 | |
|   }
 | |
|   bool isMem256_RC512() const {
 | |
|     return isMem256() && isMemIndexReg(X86::ZMM0, X86::ZMM31);
 | |
|   }
 | |
|   bool isMem512_RC256X() const {
 | |
|     return isMem512() && isMemIndexReg(X86::YMM0, X86::YMM31);
 | |
|   }
 | |
|   bool isMem512_RC512() const {
 | |
|     return isMem512() && isMemIndexReg(X86::ZMM0, X86::ZMM31);
 | |
|   }
 | |
| 
 | |
|   bool isAbsMem() const {
 | |
|     return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
 | |
|       !getMemIndexReg() && getMemScale() == 1;
 | |
|   }
 | |
|   bool isAVX512RC() const{
 | |
|       return isImm();
 | |
|   }
 | |
| 
 | |
|   bool isAbsMem16() const {
 | |
|     return isAbsMem() && Mem.ModeSize == 16;
 | |
|   }
 | |
| 
 | |
|   bool isSrcIdx() const {
 | |
|     return !getMemIndexReg() && getMemScale() == 1 &&
 | |
|       (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI ||
 | |
|        getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(getMemDisp()) &&
 | |
|       cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
 | |
|   }
 | |
|   bool isSrcIdx8() const {
 | |
|     return isMem8() && isSrcIdx();
 | |
|   }
 | |
|   bool isSrcIdx16() const {
 | |
|     return isMem16() && isSrcIdx();
 | |
|   }
 | |
|   bool isSrcIdx32() const {
 | |
|     return isMem32() && isSrcIdx();
 | |
|   }
 | |
|   bool isSrcIdx64() const {
 | |
|     return isMem64() && isSrcIdx();
 | |
|   }
 | |
| 
 | |
|   bool isDstIdx() const {
 | |
|     return !getMemIndexReg() && getMemScale() == 1 &&
 | |
|       (getMemSegReg() == 0 || getMemSegReg() == X86::ES) &&
 | |
|       (getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI ||
 | |
|        getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(getMemDisp()) &&
 | |
|       cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
 | |
|   }
 | |
|   bool isDstIdx8() const {
 | |
|     return isMem8() && isDstIdx();
 | |
|   }
 | |
|   bool isDstIdx16() const {
 | |
|     return isMem16() && isDstIdx();
 | |
|   }
 | |
|   bool isDstIdx32() const {
 | |
|     return isMem32() && isDstIdx();
 | |
|   }
 | |
|   bool isDstIdx64() const {
 | |
|     return isMem64() && isDstIdx();
 | |
|   }
 | |
| 
 | |
|   bool isMemOffs() const {
 | |
|     return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() &&
 | |
|       getMemScale() == 1;
 | |
|   }
 | |
| 
 | |
|   bool isMemOffs16_8() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 8);
 | |
|   }
 | |
|   bool isMemOffs16_16() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 16);
 | |
|   }
 | |
|   bool isMemOffs16_32() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 32);
 | |
|   }
 | |
|   bool isMemOffs32_8() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 8);
 | |
|   }
 | |
|   bool isMemOffs32_16() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 16);
 | |
|   }
 | |
|   bool isMemOffs32_32() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 32);
 | |
|   }
 | |
|   bool isMemOffs32_64() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 64);
 | |
|   }
 | |
|   bool isMemOffs64_8() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 8);
 | |
|   }
 | |
|   bool isMemOffs64_16() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 16);
 | |
|   }
 | |
|   bool isMemOffs64_32() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 32);
 | |
|   }
 | |
|   bool isMemOffs64_64() const {
 | |
|     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 64);
 | |
|   }
 | |
| 
 | |
|   bool isPrefix() const { return Kind == Prefix; }
 | |
|   bool isReg() const override { return Kind == Register; }
 | |
|   bool isDXReg() const { return Kind == DXRegister; }
 | |
| 
 | |
|   bool isGR32orGR64() const {
 | |
|     return Kind == Register &&
 | |
|       (X86MCRegisterClasses[X86::GR32RegClassID].contains(getReg()) ||
 | |
|       X86MCRegisterClasses[X86::GR64RegClassID].contains(getReg()));
 | |
|   }
 | |
| 
 | |
|   bool isVK1Pair() const {
 | |
|     return Kind == Register &&
 | |
|       X86MCRegisterClasses[X86::VK1RegClassID].contains(getReg());
 | |
|   }
 | |
| 
 | |
|   bool isVK2Pair() const {
 | |
|     return Kind == Register &&
 | |
|       X86MCRegisterClasses[X86::VK2RegClassID].contains(getReg());
 | |
|   }
 | |
| 
 | |
|   bool isVK4Pair() const {
 | |
|     return Kind == Register &&
 | |
|       X86MCRegisterClasses[X86::VK4RegClassID].contains(getReg());
 | |
|   }
 | |
| 
 | |
|   bool isVK8Pair() const {
 | |
|     return Kind == Register &&
 | |
|       X86MCRegisterClasses[X86::VK8RegClassID].contains(getReg());
 | |
|   }
 | |
| 
 | |
|   bool isVK16Pair() const {
 | |
|     return Kind == Register &&
 | |
|       X86MCRegisterClasses[X86::VK16RegClassID].contains(getReg());
 | |
|   }
 | |
| 
 | |
|   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
 | |
|     // Add as immediates when possible.
 | |
|     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
 | |
|       Inst.addOperand(MCOperand::createImm(CE->getValue()));
 | |
|     else
 | |
|       Inst.addOperand(MCOperand::createExpr(Expr));
 | |
|   }
 | |
| 
 | |
|   void addRegOperands(MCInst &Inst, unsigned N) const {
 | |
|     assert(N == 1 && "Invalid number of operands!");
 | |
|     Inst.addOperand(MCOperand::createReg(getReg()));
 | |
|   }
 | |
| 
 | |
|   void addGR32orGR64Operands(MCInst &Inst, unsigned N) const {
 | |
|     assert(N == 1 && "Invalid number of operands!");
 | |
|     MCRegister RegNo = getReg();
 | |
|     if (X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo))
 | |
|       RegNo = getX86SubSuperRegister(RegNo, 32);
 | |
|     Inst.addOperand(MCOperand::createReg(RegNo));
 | |
|   }
 | |
| 
 | |
|   void addAVX512RCOperands(MCInst &Inst, unsigned N) const {
 | |
|     assert(N == 1 && "Invalid number of operands!");
 | |
|     addExpr(Inst, getImm());
 | |
|   }
 | |
| 
 | |
|   void addImmOperands(MCInst &Inst, unsigned N) const {
 | |
|     assert(N == 1 && "Invalid number of operands!");
 | |
|     addExpr(Inst, getImm());
 | |
|   }
 | |
| 
 | |
|   void addMaskPairOperands(MCInst &Inst, unsigned N) const {
 | |
|     assert(N == 1 && "Invalid number of operands!");
 | |
|     unsigned Reg = getReg();
 | |
|     switch (Reg) {
 | |
|     case X86::K0:
 | |
|     case X86::K1:
 | |
|       Reg = X86::K0_K1;
 | |
|       break;
 | |
|     case X86::K2:
 | |
|     case X86::K3:
 | |
|       Reg = X86::K2_K3;
 | |
|       break;
 | |
|     case X86::K4:
 | |
|     case X86::K5:
 | |
|       Reg = X86::K4_K5;
 | |
|       break;
 | |
|     case X86::K6:
 | |
|     case X86::K7:
 | |
|       Reg = X86::K6_K7;
 | |
|       break;
 | |
|     }
 | |
|     Inst.addOperand(MCOperand::createReg(Reg));
 | |
|   }
 | |
| 
 | |
|   void addMemOperands(MCInst &Inst, unsigned N) const {
 | |
|     assert((N == 5) && "Invalid number of operands!");
 | |
|     Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
 | |
|     Inst.addOperand(MCOperand::createImm(getMemScale()));
 | |
|     Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
 | |
|     addExpr(Inst, getMemDisp());
 | |
|     Inst.addOperand(MCOperand::createReg(getMemSegReg()));
 | |
|   }
 | |
| 
 | |
|   void addAbsMemOperands(MCInst &Inst, unsigned N) const {
 | |
|     assert((N == 1) && "Invalid number of operands!");
 | |
|     // Add as immediates when possible.
 | |
|     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
 | |
|       Inst.addOperand(MCOperand::createImm(CE->getValue()));
 | |
|     else
 | |
|       Inst.addOperand(MCOperand::createExpr(getMemDisp()));
 | |
|   }
 | |
| 
 | |
|   void addSrcIdxOperands(MCInst &Inst, unsigned N) const {
 | |
|     assert((N == 2) && "Invalid number of operands!");
 | |
|     Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
 | |
|     Inst.addOperand(MCOperand::createReg(getMemSegReg()));
 | |
|   }
 | |
| 
 | |
|   void addDstIdxOperands(MCInst &Inst, unsigned N) const {
 | |
|     assert((N == 1) && "Invalid number of operands!");
 | |
|     Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
 | |
|   }
 | |
| 
 | |
|   void addMemOffsOperands(MCInst &Inst, unsigned N) const {
 | |
|     assert((N == 2) && "Invalid number of operands!");
 | |
|     // Add as immediates when possible.
 | |
|     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
 | |
|       Inst.addOperand(MCOperand::createImm(CE->getValue()));
 | |
|     else
 | |
|       Inst.addOperand(MCOperand::createExpr(getMemDisp()));
 | |
|     Inst.addOperand(MCOperand::createReg(getMemSegReg()));
 | |
|   }
 | |
| 
 | |
|   static std::unique_ptr<X86Operand> CreateToken(StringRef Str, SMLoc Loc) {
 | |
|     SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size());
 | |
|     auto Res = std::make_unique<X86Operand>(Token, Loc, EndLoc);
 | |
|     Res->Tok.Data = Str.data();
 | |
|     Res->Tok.Length = Str.size();
 | |
|     return Res;
 | |
|   }
 | |
| 
 | |
|   static std::unique_ptr<X86Operand>
 | |
|   CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
 | |
|             bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc(),
 | |
|             StringRef SymName = StringRef(), void *OpDecl = nullptr) {
 | |
|     auto Res = std::make_unique<X86Operand>(Register, StartLoc, EndLoc);
 | |
|     Res->Reg.RegNo = RegNo;
 | |
|     Res->AddressOf = AddressOf;
 | |
|     Res->OffsetOfLoc = OffsetOfLoc;
 | |
|     Res->SymName = SymName;
 | |
|     Res->OpDecl = OpDecl;
 | |
|     return Res;
 | |
|   }
 | |
| 
 | |
|   static std::unique_ptr<X86Operand>
 | |
|   CreateDXReg(SMLoc StartLoc, SMLoc EndLoc) {
 | |
|     return std::make_unique<X86Operand>(DXRegister, StartLoc, EndLoc);
 | |
|   }
 | |
| 
 | |
|   static std::unique_ptr<X86Operand>
 | |
|   CreatePrefix(unsigned Prefixes, SMLoc StartLoc, SMLoc EndLoc) {
 | |
|     auto Res = std::make_unique<X86Operand>(Prefix, StartLoc, EndLoc);
 | |
|     Res->Pref.Prefixes = Prefixes;
 | |
|     return Res;
 | |
|   }
 | |
| 
 | |
|   static std::unique_ptr<X86Operand> CreateImm(const MCExpr *Val,
 | |
|                                                SMLoc StartLoc, SMLoc EndLoc,
 | |
|                                                StringRef SymName = StringRef(),
 | |
|                                                void *OpDecl = nullptr,
 | |
|                                                bool GlobalRef = true) {
 | |
|     auto Res = std::make_unique<X86Operand>(Immediate, StartLoc, EndLoc);
 | |
|     Res->Imm.Val      = Val;
 | |
|     Res->Imm.LocalRef = !GlobalRef;
 | |
|     Res->SymName      = SymName;
 | |
|     Res->OpDecl       = OpDecl;
 | |
|     Res->AddressOf    = true;
 | |
|     return Res;
 | |
|   }
 | |
| 
 | |
|   /// Create an absolute memory operand.
 | |
|   static std::unique_ptr<X86Operand>
 | |
|   CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc,
 | |
|             unsigned Size = 0, StringRef SymName = StringRef(),
 | |
|             void *OpDecl = nullptr, unsigned FrontendSize = 0) {
 | |
|     auto Res = std::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
 | |
|     Res->Mem.SegReg   = 0;
 | |
|     Res->Mem.Disp     = Disp;
 | |
|     Res->Mem.BaseReg  = 0;
 | |
|     Res->Mem.IndexReg = 0;
 | |
|     Res->Mem.Scale    = 1;
 | |
|     Res->Mem.Size     = Size;
 | |
|     Res->Mem.ModeSize = ModeSize;
 | |
|     Res->Mem.FrontendSize = FrontendSize;
 | |
|     Res->SymName      = SymName;
 | |
|     Res->OpDecl       = OpDecl;
 | |
|     Res->AddressOf    = false;
 | |
|     return Res;
 | |
|   }
 | |
| 
 | |
|   /// Create a generalized memory operand.
 | |
|   static std::unique_ptr<X86Operand>
 | |
|   CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp,
 | |
|             unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc,
 | |
|             SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(),
 | |
|             void *OpDecl = nullptr, unsigned FrontendSize = 0) {
 | |
|     // We should never just have a displacement, that should be parsed as an
 | |
|     // absolute memory operand.
 | |
|     assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
 | |
| 
 | |
|     // The scale should always be one of {1,2,4,8}.
 | |
|     assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
 | |
|            "Invalid scale!");
 | |
|     auto Res = std::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
 | |
|     Res->Mem.SegReg   = SegReg;
 | |
|     Res->Mem.Disp     = Disp;
 | |
|     Res->Mem.BaseReg  = BaseReg;
 | |
|     Res->Mem.IndexReg = IndexReg;
 | |
|     Res->Mem.Scale    = Scale;
 | |
|     Res->Mem.Size     = Size;
 | |
|     Res->Mem.ModeSize = ModeSize;
 | |
|     Res->Mem.FrontendSize = FrontendSize;
 | |
|     Res->SymName      = SymName;
 | |
|     Res->OpDecl       = OpDecl;
 | |
|     Res->AddressOf    = false;
 | |
|     return Res;
 | |
|   }
 | |
| };
 | |
| 
 | |
| } // end namespace llvm
 | |
| 
 | |
| #endif // LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
 |