1 //===-- X86Operand.h - Parsed X86 machine instruction --------------------===//
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 "X86AsmParserCommon.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCInst.h"
16 #include "llvm/MC/MCRegisterInfo.h"
17 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18 #include "llvm/ADT/STLExtras.h"
19 #include "MCTargetDesc/X86MCTargetDesc.h"
23 /// X86Operand - Instances of this class represent a parsed X86 machine
25 struct X86Operand : public MCParsedAsmOperand {
33 SMLoc StartLoc, EndLoc;
69 X86Operand(KindTy K, SMLoc Start, SMLoc End)
70 : Kind(K), StartLoc(Start), EndLoc(End) {}
72 StringRef getSymName() override { return SymName; }
73 void *getOpDecl() override { return OpDecl; }
75 /// getStartLoc - Get the location of the first token of this operand.
76 SMLoc getStartLoc() const override { return StartLoc; }
77 /// getEndLoc - Get the location of the last token of this operand.
78 SMLoc getEndLoc() const override { return EndLoc; }
79 /// getLocRange - Get the range between the first and last token of this
81 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
82 /// getOffsetOfLoc - Get the location of the offset operator.
83 SMLoc getOffsetOfLoc() const override { return OffsetOfLoc; }
85 void print(raw_ostream &OS) const override {}
87 StringRef getToken() const {
88 assert(Kind == Token && "Invalid access!");
89 return StringRef(Tok.Data, Tok.Length);
91 void setTokenValue(StringRef Value) {
92 assert(Kind == Token && "Invalid access!");
93 Tok.Data = Value.data();
94 Tok.Length = Value.size();
97 unsigned getReg() const override {
98 assert(Kind == Register && "Invalid access!");
102 const MCExpr *getImm() const {
103 assert(Kind == Immediate && "Invalid access!");
107 const MCExpr *getMemDisp() const {
108 assert(Kind == Memory && "Invalid access!");
111 unsigned getMemSegReg() const {
112 assert(Kind == Memory && "Invalid access!");
115 unsigned getMemBaseReg() const {
116 assert(Kind == Memory && "Invalid access!");
119 unsigned getMemIndexReg() const {
120 assert(Kind == Memory && "Invalid access!");
123 unsigned getMemScale() const {
124 assert(Kind == Memory && "Invalid access!");
127 unsigned getMemModeSize() const {
128 assert(Kind == Memory && "Invalid access!");
132 bool isToken() const override {return Kind == Token; }
134 bool isImm() const override { return Kind == Immediate; }
136 bool isImmSExti16i8() const {
140 // If this isn't a constant expr, just assume it fits and let relaxation
142 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
146 // Otherwise, check the value is in a range that makes sense for this
148 return isImmSExti16i8Value(CE->getValue());
150 bool isImmSExti32i8() const {
154 // If this isn't a constant expr, just assume it fits and let relaxation
156 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
160 // Otherwise, check the value is in a range that makes sense for this
162 return isImmSExti32i8Value(CE->getValue());
164 bool isImmSExti64i8() const {
168 // If this isn't a constant expr, just assume it fits and let relaxation
170 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
174 // Otherwise, check the value is in a range that makes sense for this
176 return isImmSExti64i8Value(CE->getValue());
178 bool isImmSExti64i32() const {
182 // If this isn't a constant expr, just assume it fits and let relaxation
184 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
188 // Otherwise, check the value is in a range that makes sense for this
190 return isImmSExti64i32Value(CE->getValue());
193 bool isImmUnsignedi8() const {
194 if (!isImm()) return false;
195 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
196 if (!CE) return false;
197 return isImmUnsignedi8Value(CE->getValue());
200 bool isOffsetOf() const override {
201 return OffsetOfLoc.getPointer();
204 bool needAddressOf() const override {
208 bool isMem() const override { return Kind == Memory; }
209 bool isMemUnsized() const {
210 return Kind == Memory && Mem.Size == 0;
212 bool isMem8() const {
213 return Kind == Memory && (!Mem.Size || Mem.Size == 8);
215 bool isMem16() const {
216 return Kind == Memory && (!Mem.Size || Mem.Size == 16);
218 bool isMem32() const {
219 return Kind == Memory && (!Mem.Size || Mem.Size == 32);
221 bool isMem64() const {
222 return Kind == Memory && (!Mem.Size || Mem.Size == 64);
224 bool isMem80() const {
225 return Kind == Memory && (!Mem.Size || Mem.Size == 80);
227 bool isMem128() const {
228 return Kind == Memory && (!Mem.Size || Mem.Size == 128);
230 bool isMem256() const {
231 return Kind == Memory && (!Mem.Size || Mem.Size == 256);
233 bool isMem512() const {
234 return Kind == Memory && (!Mem.Size || Mem.Size == 512);
237 bool isMemVX32() const {
238 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
239 getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15;
241 bool isMemVX32X() const {
242 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
243 getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM31;
245 bool isMemVY32() const {
246 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
247 getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15;
249 bool isMemVY32X() const {
250 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
251 getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM31;
253 bool isMemVX64() const {
254 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
255 getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15;
257 bool isMemVX64X() const {
258 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
259 getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM31;
261 bool isMemVY64() const {
262 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
263 getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15;
265 bool isMemVY64X() const {
266 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
267 getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM31;
269 bool isMemVZ32() const {
270 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
271 getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31;
273 bool isMemVZ64() const {
274 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
275 getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31;
278 bool isAbsMem() const {
279 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
280 !getMemIndexReg() && getMemScale() == 1;
282 bool isAVX512RC() const{
286 bool isAbsMem16() const {
287 return isAbsMem() && Mem.ModeSize == 16;
290 bool isSrcIdx() const {
291 return !getMemIndexReg() && getMemScale() == 1 &&
292 (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI ||
293 getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(getMemDisp()) &&
294 cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
296 bool isSrcIdx8() const {
297 return isMem8() && isSrcIdx();
299 bool isSrcIdx16() const {
300 return isMem16() && isSrcIdx();
302 bool isSrcIdx32() const {
303 return isMem32() && isSrcIdx();
305 bool isSrcIdx64() const {
306 return isMem64() && isSrcIdx();
309 bool isDstIdx() const {
310 return !getMemIndexReg() && getMemScale() == 1 &&
311 (getMemSegReg() == 0 || getMemSegReg() == X86::ES) &&
312 (getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI ||
313 getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(getMemDisp()) &&
314 cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
316 bool isDstIdx8() const {
317 return isMem8() && isDstIdx();
319 bool isDstIdx16() const {
320 return isMem16() && isDstIdx();
322 bool isDstIdx32() const {
323 return isMem32() && isDstIdx();
325 bool isDstIdx64() const {
326 return isMem64() && isDstIdx();
329 bool isMemOffs() const {
330 return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() &&
334 bool isMemOffs16_8() const {
335 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 8);
337 bool isMemOffs16_16() const {
338 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 16);
340 bool isMemOffs16_32() const {
341 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 32);
343 bool isMemOffs32_8() const {
344 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 8);
346 bool isMemOffs32_16() const {
347 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 16);
349 bool isMemOffs32_32() const {
350 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 32);
352 bool isMemOffs32_64() const {
353 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 64);
355 bool isMemOffs64_8() const {
356 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 8);
358 bool isMemOffs64_16() const {
359 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 16);
361 bool isMemOffs64_32() const {
362 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 32);
364 bool isMemOffs64_64() const {
365 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 64);
368 bool isReg() const override { return Kind == Register; }
370 bool isGR32orGR64() const {
371 return Kind == Register &&
372 (X86MCRegisterClasses[X86::GR32RegClassID].contains(getReg()) ||
373 X86MCRegisterClasses[X86::GR64RegClassID].contains(getReg()));
376 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
377 // Add as immediates when possible.
378 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
379 Inst.addOperand(MCOperand::createImm(CE->getValue()));
381 Inst.addOperand(MCOperand::createExpr(Expr));
384 void addRegOperands(MCInst &Inst, unsigned N) const {
385 assert(N == 1 && "Invalid number of operands!");
386 Inst.addOperand(MCOperand::createReg(getReg()));
389 static unsigned getGR32FromGR64(unsigned RegNo) {
391 default: llvm_unreachable("Unexpected register");
392 case X86::RAX: return X86::EAX;
393 case X86::RCX: return X86::ECX;
394 case X86::RDX: return X86::EDX;
395 case X86::RBX: return X86::EBX;
396 case X86::RBP: return X86::EBP;
397 case X86::RSP: return X86::ESP;
398 case X86::RSI: return X86::ESI;
399 case X86::RDI: return X86::EDI;
400 case X86::R8: return X86::R8D;
401 case X86::R9: return X86::R9D;
402 case X86::R10: return X86::R10D;
403 case X86::R11: return X86::R11D;
404 case X86::R12: return X86::R12D;
405 case X86::R13: return X86::R13D;
406 case X86::R14: return X86::R14D;
407 case X86::R15: return X86::R15D;
408 case X86::RIP: return X86::EIP;
412 void addGR32orGR64Operands(MCInst &Inst, unsigned N) const {
413 assert(N == 1 && "Invalid number of operands!");
414 unsigned RegNo = getReg();
415 if (X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo))
416 RegNo = getGR32FromGR64(RegNo);
417 Inst.addOperand(MCOperand::createReg(RegNo));
419 void addAVX512RCOperands(MCInst &Inst, unsigned N) const {
420 assert(N == 1 && "Invalid number of operands!");
421 addExpr(Inst, getImm());
423 void addImmOperands(MCInst &Inst, unsigned N) const {
424 assert(N == 1 && "Invalid number of operands!");
425 addExpr(Inst, getImm());
428 void addMemOperands(MCInst &Inst, unsigned N) const {
429 assert((N == 5) && "Invalid number of operands!");
430 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
431 Inst.addOperand(MCOperand::createImm(getMemScale()));
432 Inst.addOperand(MCOperand::createReg(getMemIndexReg()));
433 addExpr(Inst, getMemDisp());
434 Inst.addOperand(MCOperand::createReg(getMemSegReg()));
437 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
438 assert((N == 1) && "Invalid number of operands!");
439 // Add as immediates when possible.
440 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
441 Inst.addOperand(MCOperand::createImm(CE->getValue()));
443 Inst.addOperand(MCOperand::createExpr(getMemDisp()));
446 void addSrcIdxOperands(MCInst &Inst, unsigned N) const {
447 assert((N == 2) && "Invalid number of operands!");
448 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
449 Inst.addOperand(MCOperand::createReg(getMemSegReg()));
451 void addDstIdxOperands(MCInst &Inst, unsigned N) const {
452 assert((N == 1) && "Invalid number of operands!");
453 Inst.addOperand(MCOperand::createReg(getMemBaseReg()));
456 void addMemOffsOperands(MCInst &Inst, unsigned N) const {
457 assert((N == 2) && "Invalid number of operands!");
458 // Add as immediates when possible.
459 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
460 Inst.addOperand(MCOperand::createImm(CE->getValue()));
462 Inst.addOperand(MCOperand::createExpr(getMemDisp()));
463 Inst.addOperand(MCOperand::createReg(getMemSegReg()));
466 static std::unique_ptr<X86Operand> CreateToken(StringRef Str, SMLoc Loc) {
467 SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size());
468 auto Res = llvm::make_unique<X86Operand>(Token, Loc, EndLoc);
469 Res->Tok.Data = Str.data();
470 Res->Tok.Length = Str.size();
474 static std::unique_ptr<X86Operand>
475 CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
476 bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc(),
477 StringRef SymName = StringRef(), void *OpDecl = nullptr) {
478 auto Res = llvm::make_unique<X86Operand>(Register, StartLoc, EndLoc);
479 Res->Reg.RegNo = RegNo;
480 Res->AddressOf = AddressOf;
481 Res->OffsetOfLoc = OffsetOfLoc;
482 Res->SymName = SymName;
483 Res->OpDecl = OpDecl;
487 static std::unique_ptr<X86Operand> CreateImm(const MCExpr *Val,
488 SMLoc StartLoc, SMLoc EndLoc) {
489 auto Res = llvm::make_unique<X86Operand>(Immediate, StartLoc, EndLoc);
494 /// Create an absolute memory operand.
495 static std::unique_ptr<X86Operand>
496 CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc,
497 unsigned Size = 0, StringRef SymName = StringRef(),
498 void *OpDecl = nullptr) {
499 auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
501 Res->Mem.Disp = Disp;
502 Res->Mem.BaseReg = 0;
503 Res->Mem.IndexReg = 0;
505 Res->Mem.Size = Size;
506 Res->Mem.ModeSize = ModeSize;
507 Res->SymName = SymName;
508 Res->OpDecl = OpDecl;
509 Res->AddressOf = false;
513 /// Create a generalized memory operand.
514 static std::unique_ptr<X86Operand>
515 CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp,
516 unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc,
517 SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(),
518 void *OpDecl = nullptr) {
519 // We should never just have a displacement, that should be parsed as an
520 // absolute memory operand.
521 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
523 // The scale should always be one of {1,2,4,8}.
524 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
526 auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
527 Res->Mem.SegReg = SegReg;
528 Res->Mem.Disp = Disp;
529 Res->Mem.BaseReg = BaseReg;
530 Res->Mem.IndexReg = IndexReg;
531 Res->Mem.Scale = Scale;
532 Res->Mem.Size = Size;
533 Res->Mem.ModeSize = ModeSize;
534 Res->SymName = SymName;
535 Res->OpDecl = OpDecl;
536 Res->AddressOf = false;
541 } // End of namespace llvm