1 //===- X86Operand.h - Parsed X86 machine instruction ------------*- C++ -*-===//
3 // The LLVM Compiler Infrastructure
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
8 //===----------------------------------------------------------------------===//
10 #ifndef LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
11 #define LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
13 #include "InstPrinter/X86IntelInstPrinter.h"
14 #include "MCTargetDesc/X86MCTargetDesc.h"
15 #include "X86AsmParserCommon.h"
16 #include "llvm/ADT/STLExtras.h"
17 #include "llvm/ADT/StringRef.h"
18 #include "llvm/MC/MCExpr.h"
19 #include "llvm/MC/MCInst.h"
20 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
21 #include "llvm/MC/MCRegisterInfo.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include "llvm/Support/SMLoc.h"
30 /// X86Operand - Instances of this class represent a parsed X86 machine
32 struct X86Operand final : public MCParsedAsmOperand {
33 enum KindTy { Token, Register, Immediate, Memory, Prefix, DXRegister } Kind;
35 SMLoc StartLoc, EndLoc;
67 /// If the memory operand is unsized and there are multiple instruction
68 /// matches, prefer the one with this size.
69 unsigned FrontendSize;
80 X86Operand(KindTy K, SMLoc Start, SMLoc End)
81 : Kind(K), StartLoc(Start), EndLoc(End) {}
83 StringRef getSymName() override { return SymName; }
84 void *getOpDecl() override { return OpDecl; }
86 /// getStartLoc - Get the location of the first token of this operand.
87 SMLoc getStartLoc() const override { return StartLoc; }
89 /// getEndLoc - Get the location of the last token of this operand.
90 SMLoc getEndLoc() const override { return EndLoc; }
92 /// getLocRange - Get the range between the first and last token of this
94 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
96 /// getOffsetOfLoc - Get the location of the offset operator.
97 SMLoc getOffsetOfLoc() const override { return OffsetOfLoc; }
99 void print(raw_ostream &OS) const override {
101 auto PrintImmValue = [&](const MCExpr *Val, const char *VName) {
102 if (Val->getKind() == MCExpr::Constant) {
103 if (auto Imm = cast<MCConstantExpr>(Val)->getValue())
105 } else if (Val->getKind() == MCExpr::SymbolRef) {
106 if (auto *SRE = dyn_cast<MCSymbolRefExpr>(Val)) {
107 const MCSymbol &Sym = SRE->getSymbol();
108 if (auto SymName = Sym.getName().data())
109 OS << VName << SymName;
119 OS << "Reg:" << X86IntelInstPrinter::getRegisterName(Reg.RegNo);
125 PrintImmValue(Imm.Val, "Imm:");
128 OS << "Prefix:" << Pref.Prefixes;
131 OS << "Memory: ModeSize=" << Mem.ModeSize;
133 OS << ",Size=" << Mem.Size;
135 OS << ",BaseReg=" << X86IntelInstPrinter::getRegisterName(Mem.BaseReg);
138 << X86IntelInstPrinter::getRegisterName(Mem.IndexReg);
140 OS << ",Scale=" << Mem.Scale;
142 PrintImmValue(Mem.Disp, ",Disp=");
144 OS << ",SegReg=" << X86IntelInstPrinter::getRegisterName(Mem.SegReg);
149 StringRef getToken() const {
150 assert(Kind == Token && "Invalid access!");
151 return StringRef(Tok.Data, Tok.Length);
153 void setTokenValue(StringRef Value) {
154 assert(Kind == Token && "Invalid access!");
155 Tok.Data = Value.data();
156 Tok.Length = Value.size();
159 unsigned getReg() const override {
160 assert(Kind == Register && "Invalid access!");
164 unsigned getPrefix() const {
165 assert(Kind == Prefix && "Invalid access!");
166 return Pref.Prefixes;
169 const MCExpr *getImm() const {
170 assert(Kind == Immediate && "Invalid access!");
174 const MCExpr *getMemDisp() const {
175 assert(Kind == Memory && "Invalid access!");
178 unsigned getMemSegReg() const {
179 assert(Kind == Memory && "Invalid access!");
182 unsigned getMemBaseReg() const {
183 assert(Kind == Memory && "Invalid access!");
186 unsigned getMemIndexReg() const {
187 assert(Kind == Memory && "Invalid access!");
190 unsigned getMemScale() const {
191 assert(Kind == Memory && "Invalid access!");
194 unsigned getMemModeSize() const {
195 assert(Kind == Memory && "Invalid access!");
198 unsigned getMemFrontendSize() const {
199 assert(Kind == Memory && "Invalid access!");
200 return Mem.FrontendSize;
203 bool isToken() const override {return Kind == Token; }
205 bool isImm() const override { return Kind == Immediate; }
207 bool isImmSExti16i8() const {
211 // If this isn't a constant expr, just assume it fits and let relaxation
213 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
217 // Otherwise, check the value is in a range that makes sense for this
219 return isImmSExti16i8Value(CE->getValue());
221 bool isImmSExti32i8() const {
225 // If this isn't a constant expr, just assume it fits and let relaxation
227 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
231 // Otherwise, check the value is in a range that makes sense for this
233 return isImmSExti32i8Value(CE->getValue());
235 bool isImmSExti64i8() const {
239 // If this isn't a constant expr, just assume it fits and let relaxation
241 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
245 // Otherwise, check the value is in a range that makes sense for this
247 return isImmSExti64i8Value(CE->getValue());
249 bool isImmSExti64i32() const {
253 // If this isn't a constant expr, just assume it fits and let relaxation
255 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
259 // Otherwise, check the value is in a range that makes sense for this
261 return isImmSExti64i32Value(CE->getValue());
264 bool isImmUnsignedi8() const {
265 if (!isImm()) return false;
266 // If this isn't a constant expr, just assume it fits and let relaxation
268 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
269 if (!CE) return true;
270 return isImmUnsignedi8Value(CE->getValue());
273 bool isOffsetOf() const override {
274 return OffsetOfLoc.getPointer();
277 bool needAddressOf() const override {
281 bool isMem() const override { return Kind == Memory; }
282 bool isMemUnsized() const {
283 return Kind == Memory && Mem.Size == 0;
285 bool isMem8() const {
286 return Kind == Memory && (!Mem.Size || Mem.Size == 8);
288 bool isMem16() const {
289 return Kind == Memory && (!Mem.Size || Mem.Size == 16);
291 bool isMem32() const {
292 return Kind == Memory && (!Mem.Size || Mem.Size == 32);
294 bool isMem64() const {
295 return Kind == Memory && (!Mem.Size || Mem.Size == 64);
297 bool isMem80() const {
298 return Kind == Memory && (!Mem.Size || Mem.Size == 80);
300 bool isMem128() const {
301 return Kind == Memory && (!Mem.Size || Mem.Size == 128);
303 bool isMem256() const {
304 return Kind == Memory && (!Mem.Size || Mem.Size == 256);
306 bool isMem512() const {
307 return Kind == Memory && (!Mem.Size || Mem.Size == 512);
309 bool isMemIndexReg(unsigned LowR, unsigned HighR) const {
310 assert(Kind == Memory && "Invalid access!");
311 return Mem.IndexReg >= LowR && Mem.IndexReg <= HighR;
314 bool isMem64_RC128() const {
315 return isMem64() && isMemIndexReg(X86::XMM0, X86::XMM15);
317 bool isMem128_RC128() const {
318 return isMem128() && isMemIndexReg(X86::XMM0, X86::XMM15);
320 bool isMem128_RC256() const {
321 return isMem128() && isMemIndexReg(X86::YMM0, X86::YMM15);
323 bool isMem256_RC128() const {
324 return isMem256() && isMemIndexReg(X86::XMM0, X86::XMM15);
326 bool isMem256_RC256() const {
327 return isMem256() && isMemIndexReg(X86::YMM0, X86::YMM15);
330 bool isMem64_RC128X() const {
331 return isMem64() && isMemIndexReg(X86::XMM0, X86::XMM31);
333 bool isMem128_RC128X() const {
334 return isMem128() && isMemIndexReg(X86::XMM0, X86::XMM31);
336 bool isMem128_RC256X() const {
337 return isMem128() && isMemIndexReg(X86::YMM0, X86::YMM31);
339 bool isMem256_RC128X() const {
340 return isMem256() && isMemIndexReg(X86::XMM0, X86::XMM31);
342 bool isMem256_RC256X() const {
343 return isMem256() && isMemIndexReg(X86::YMM0, X86::YMM31);
345 bool isMem256_RC512() const {
346 return isMem256() && isMemIndexReg(X86::ZMM0, X86::ZMM31);
348 bool isMem512_RC256X() const {
349 return isMem512() && isMemIndexReg(X86::YMM0, X86::YMM31);
351 bool isMem512_RC512() const {
352 return isMem512() && isMemIndexReg(X86::ZMM0, X86::ZMM31);
355 bool isAbsMem() const {
356 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
357 !getMemIndexReg() && getMemScale() == 1;
359 bool isAVX512RC() const{
363 bool isAbsMem16() const {
364 return isAbsMem() && Mem.ModeSize == 16;
367 bool isSrcIdx() const {
368 return !getMemIndexReg() && getMemScale() == 1 &&
369 (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI ||
370 getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(getMemDisp()) &&
371 cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
373 bool isSrcIdx8() const {
374 return isMem8() && isSrcIdx();
376 bool isSrcIdx16() const {
377 return isMem16() && isSrcIdx();
379 bool isSrcIdx32() const {
380 return isMem32() && isSrcIdx();
382 bool isSrcIdx64() const {
383 return isMem64() && isSrcIdx();
386 bool isDstIdx() const {
387 return !getMemIndexReg() && getMemScale() == 1 &&
388 (getMemSegReg() == 0 || getMemSegReg() == X86::ES) &&
389 (getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI ||
390 getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(getMemDisp()) &&
391 cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
393 bool isDstIdx8() const {
394 return isMem8() && isDstIdx();
396 bool isDstIdx16() const {
397 return isMem16() && isDstIdx();
399 bool isDstIdx32() const {
400 return isMem32() && isDstIdx();
402 bool isDstIdx64() const {
403 return isMem64() && isDstIdx();
406 bool isMemOffs() const {
407 return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() &&
411 bool isMemOffs16_8() const {
412 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 8);
414 bool isMemOffs16_16() const {
415 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 16);
417 bool isMemOffs16_32() const {
418 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 32);
420 bool isMemOffs32_8() const {
421 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 8);
423 bool isMemOffs32_16() const {
424 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 16);
426 bool isMemOffs32_32() const {
427 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 32);
429 bool isMemOffs32_64() const {
430 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 64);
432 bool isMemOffs64_8() const {
433 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 8);
435 bool isMemOffs64_16() const {
436 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 16);
438 bool isMemOffs64_32() const {
439 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 32);
441 bool isMemOffs64_64() const {
442 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 64);
445 bool isPrefix() const { return Kind == Prefix; }
446 bool isReg() const override { return Kind == Register; }
447 bool isDXReg() const { return Kind == DXRegister; }
449 bool isGR32orGR64() const {
450 return Kind == Register &&
451 (X86MCRegisterClasses[X86::GR32RegClassID].contains(getReg()) ||
452 X86MCRegisterClasses[X86::GR64RegClassID].contains(getReg()));
455 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
456 // Add as immediates when possible.
457 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
458 Inst.addOperand(MCOperand::createImm(CE->getValue()));
460 Inst.addOperand(MCOperand::createExpr(Expr));
463 void addRegOperands(MCInst &Inst, unsigned N) const {
464 assert(N == 1 && "Invalid number of operands!");
465 Inst.addOperand(MCOperand::createReg(getReg()));
468 void addGR32orGR64Operands(MCInst &Inst, unsigned N) const {
469 assert(N == 1 && "Invalid number of operands!");
470 unsigned RegNo = getReg();
471 if (X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo))
472 RegNo = getX86SubSuperRegister(RegNo, 32);
473 Inst.addOperand(MCOperand::createReg(RegNo));
476 void addAVX512RCOperands(MCInst &Inst, unsigned N) const {
477 assert(N == 1 && "Invalid number of operands!");
478 addExpr(Inst, getImm());
481 void addImmOperands(MCInst &Inst, unsigned N) const {
482 assert(N == 1 && "Invalid number of operands!");
483 addExpr(Inst, getImm());
486 void addMemOperands(MCInst &Inst, unsigned N) const {
487 assert((N == 5) && "Invalid number of operands!");
488 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
489 Inst.addOperand(MCOperand::createImm(getMemScale()));
490 Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
491 addExpr(Inst, getMemDisp());
492 Inst.addOperand(MCOperand::createReg(getMemSegReg()));
495 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
496 assert((N == 1) && "Invalid number of operands!");
497 // Add as immediates when possible.
498 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
499 Inst.addOperand(MCOperand::createImm(CE->getValue()));
501 Inst.addOperand(MCOperand::createExpr(getMemDisp()));
504 void addSrcIdxOperands(MCInst &Inst, unsigned N) const {
505 assert((N == 2) && "Invalid number of operands!");
506 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
507 Inst.addOperand(MCOperand::createReg(getMemSegReg()));
510 void addDstIdxOperands(MCInst &Inst, unsigned N) const {
511 assert((N == 1) && "Invalid number of operands!");
512 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
515 void addMemOffsOperands(MCInst &Inst, unsigned N) const {
516 assert((N == 2) && "Invalid number of operands!");
517 // Add as immediates when possible.
518 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
519 Inst.addOperand(MCOperand::createImm(CE->getValue()));
521 Inst.addOperand(MCOperand::createExpr(getMemDisp()));
522 Inst.addOperand(MCOperand::createReg(getMemSegReg()));
525 static std::unique_ptr<X86Operand> CreateToken(StringRef Str, SMLoc Loc) {
526 SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size());
527 auto Res = llvm::make_unique<X86Operand>(Token, Loc, EndLoc);
528 Res->Tok.Data = Str.data();
529 Res->Tok.Length = Str.size();
533 static std::unique_ptr<X86Operand>
534 CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
535 bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc(),
536 StringRef SymName = StringRef(), void *OpDecl = nullptr) {
537 auto Res = llvm::make_unique<X86Operand>(Register, StartLoc, EndLoc);
538 Res->Reg.RegNo = RegNo;
539 Res->AddressOf = AddressOf;
540 Res->OffsetOfLoc = OffsetOfLoc;
541 Res->SymName = SymName;
542 Res->OpDecl = OpDecl;
546 static std::unique_ptr<X86Operand>
547 CreateDXReg(SMLoc StartLoc, SMLoc EndLoc) {
548 return llvm::make_unique<X86Operand>(DXRegister, StartLoc, EndLoc);
551 static std::unique_ptr<X86Operand>
552 CreatePrefix(unsigned Prefixes, SMLoc StartLoc, SMLoc EndLoc) {
553 auto Res = llvm::make_unique<X86Operand>(Prefix, StartLoc, EndLoc);
554 Res->Pref.Prefixes = Prefixes;
558 static std::unique_ptr<X86Operand> CreateImm(const MCExpr *Val,
559 SMLoc StartLoc, SMLoc EndLoc) {
560 auto Res = llvm::make_unique<X86Operand>(Immediate, StartLoc, EndLoc);
565 /// Create an absolute memory operand.
566 static std::unique_ptr<X86Operand>
567 CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc,
568 unsigned Size = 0, StringRef SymName = StringRef(),
569 void *OpDecl = nullptr, unsigned FrontendSize = 0) {
570 auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
572 Res->Mem.Disp = Disp;
573 Res->Mem.BaseReg = 0;
574 Res->Mem.IndexReg = 0;
576 Res->Mem.Size = Size;
577 Res->Mem.ModeSize = ModeSize;
578 Res->Mem.FrontendSize = FrontendSize;
579 Res->SymName = SymName;
580 Res->OpDecl = OpDecl;
581 Res->AddressOf = false;
585 /// Create a generalized memory operand.
586 static std::unique_ptr<X86Operand>
587 CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp,
588 unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc,
589 SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(),
590 void *OpDecl = nullptr, unsigned FrontendSize = 0) {
591 // We should never just have a displacement, that should be parsed as an
592 // absolute memory operand.
593 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
595 // The scale should always be one of {1,2,4,8}.
596 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
598 auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
599 Res->Mem.SegReg = SegReg;
600 Res->Mem.Disp = Disp;
601 Res->Mem.BaseReg = BaseReg;
602 Res->Mem.IndexReg = IndexReg;
603 Res->Mem.Scale = Scale;
604 Res->Mem.Size = Size;
605 Res->Mem.ModeSize = ModeSize;
606 Res->Mem.FrontendSize = FrontendSize;
607 Res->SymName = SymName;
608 Res->OpDecl = OpDecl;
609 Res->AddressOf = false;
614 } // end namespace llvm
616 #endif // LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H