1 //===-- X86Operand.h - Parsed X86 machine instruction --------------------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 
10 #ifndef LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
11 #define LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
12 
13 #include "X86AsmParserCommon.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
16 #include "llvm/ADT/STLExtras.h"
17 
18 namespace llvm {
19 
20 /// X86Operand - Instances of this class represent a parsed X86 machine
21 /// instruction.
22 struct X86Operand : public MCParsedAsmOperand {
23   enum KindTy {
24     Token,
25     Register,
26     Immediate,
27     Memory
28   } Kind;
29 
30   SMLoc StartLoc, EndLoc;
31   SMLoc OffsetOfLoc;
32   StringRef SymName;
33   void *OpDecl;
34   bool AddressOf;
35 
36   struct TokOp {
37     const char *Data;
38     unsigned Length;
39   };
40 
41   struct RegOp {
42     unsigned RegNo;
43   };
44 
45   struct ImmOp {
46     const MCExpr *Val;
47   };
48 
49   struct MemOp {
50     unsigned SegReg;
51     const MCExpr *Disp;
52     unsigned BaseReg;
53     unsigned IndexReg;
54     unsigned Scale;
55     unsigned Size;
56     unsigned ModeSize;
57   };
58 
59   union {
60     struct TokOp Tok;
61     struct RegOp Reg;
62     struct ImmOp Imm;
63     struct MemOp Mem;
64   };
65 
X86OperandX86Operand66   X86Operand(KindTy K, SMLoc Start, SMLoc End)
67     : Kind(K), StartLoc(Start), EndLoc(End) {}
68 
getSymNameX86Operand69   StringRef getSymName() override { return SymName; }
getOpDeclX86Operand70   void *getOpDecl() override { return OpDecl; }
71 
72   /// getStartLoc - Get the location of the first token of this operand.
getStartLocX86Operand73   SMLoc getStartLoc() const override { return StartLoc; }
74   /// getEndLoc - Get the location of the last token of this operand.
getEndLocX86Operand75   SMLoc getEndLoc() const override { return EndLoc; }
76   /// getLocRange - Get the range between the first and last token of this
77   /// operand.
getLocRangeX86Operand78   SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
79   /// getOffsetOfLoc - Get the location of the offset operator.
getOffsetOfLocX86Operand80   SMLoc getOffsetOfLoc() const override { return OffsetOfLoc; }
81 
printX86Operand82   void print(raw_ostream &OS) const override {}
83 
getTokenX86Operand84   StringRef getToken() const {
85     assert(Kind == Token && "Invalid access!");
86     return StringRef(Tok.Data, Tok.Length);
87   }
setTokenValueX86Operand88   void setTokenValue(StringRef Value) {
89     assert(Kind == Token && "Invalid access!");
90     Tok.Data = Value.data();
91     Tok.Length = Value.size();
92   }
93 
getRegX86Operand94   unsigned getReg() const override {
95     assert(Kind == Register && "Invalid access!");
96     return Reg.RegNo;
97   }
98 
getImmX86Operand99   const MCExpr *getImm() const {
100     assert(Kind == Immediate && "Invalid access!");
101     return Imm.Val;
102   }
103 
getMemDispX86Operand104   const MCExpr *getMemDisp() const {
105     assert(Kind == Memory && "Invalid access!");
106     return Mem.Disp;
107   }
getMemSegRegX86Operand108   unsigned getMemSegReg() const {
109     assert(Kind == Memory && "Invalid access!");
110     return Mem.SegReg;
111   }
getMemBaseRegX86Operand112   unsigned getMemBaseReg() const {
113     assert(Kind == Memory && "Invalid access!");
114     return Mem.BaseReg;
115   }
getMemIndexRegX86Operand116   unsigned getMemIndexReg() const {
117     assert(Kind == Memory && "Invalid access!");
118     return Mem.IndexReg;
119   }
getMemScaleX86Operand120   unsigned getMemScale() const {
121     assert(Kind == Memory && "Invalid access!");
122     return Mem.Scale;
123   }
getMemModeSizeX86Operand124   unsigned getMemModeSize() const {
125     assert(Kind == Memory && "Invalid access!");
126     return Mem.ModeSize;
127   }
128 
isTokenX86Operand129   bool isToken() const override {return Kind == Token; }
130 
isImmX86Operand131   bool isImm() const override { return Kind == Immediate; }
132 
isImmSExti16i8X86Operand133   bool isImmSExti16i8() const {
134     if (!isImm())
135       return false;
136 
137     // If this isn't a constant expr, just assume it fits and let relaxation
138     // handle it.
139     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
140     if (!CE)
141       return true;
142 
143     // Otherwise, check the value is in a range that makes sense for this
144     // extension.
145     return isImmSExti16i8Value(CE->getValue());
146   }
isImmSExti32i8X86Operand147   bool isImmSExti32i8() const {
148     if (!isImm())
149       return false;
150 
151     // If this isn't a constant expr, just assume it fits and let relaxation
152     // handle it.
153     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
154     if (!CE)
155       return true;
156 
157     // Otherwise, check the value is in a range that makes sense for this
158     // extension.
159     return isImmSExti32i8Value(CE->getValue());
160   }
isImmSExti64i8X86Operand161   bool isImmSExti64i8() const {
162     if (!isImm())
163       return false;
164 
165     // If this isn't a constant expr, just assume it fits and let relaxation
166     // handle it.
167     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
168     if (!CE)
169       return true;
170 
171     // Otherwise, check the value is in a range that makes sense for this
172     // extension.
173     return isImmSExti64i8Value(CE->getValue());
174   }
isImmSExti64i32X86Operand175   bool isImmSExti64i32() const {
176     if (!isImm())
177       return false;
178 
179     // If this isn't a constant expr, just assume it fits and let relaxation
180     // handle it.
181     const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
182     if (!CE)
183       return true;
184 
185     // Otherwise, check the value is in a range that makes sense for this
186     // extension.
187     return isImmSExti64i32Value(CE->getValue());
188   }
189 
isOffsetOfX86Operand190   bool isOffsetOf() const override {
191     return OffsetOfLoc.getPointer();
192   }
193 
needAddressOfX86Operand194   bool needAddressOf() const override {
195     return AddressOf;
196   }
197 
isMemX86Operand198   bool isMem() const override { return Kind == Memory; }
isMemUnsizedX86Operand199   bool isMemUnsized() const {
200     return Kind == Memory && Mem.Size == 0;
201   }
isMem8X86Operand202   bool isMem8() const {
203     return Kind == Memory && (!Mem.Size || Mem.Size == 8);
204   }
isMem16X86Operand205   bool isMem16() const {
206     return Kind == Memory && (!Mem.Size || Mem.Size == 16);
207   }
isMem32X86Operand208   bool isMem32() const {
209     return Kind == Memory && (!Mem.Size || Mem.Size == 32);
210   }
isMem64X86Operand211   bool isMem64() const {
212     return Kind == Memory && (!Mem.Size || Mem.Size == 64);
213   }
isMem80X86Operand214   bool isMem80() const {
215     return Kind == Memory && (!Mem.Size || Mem.Size == 80);
216   }
isMem128X86Operand217   bool isMem128() const {
218     return Kind == Memory && (!Mem.Size || Mem.Size == 128);
219   }
isMem256X86Operand220   bool isMem256() const {
221     return Kind == Memory && (!Mem.Size || Mem.Size == 256);
222   }
isMem512X86Operand223   bool isMem512() const {
224     return Kind == Memory && (!Mem.Size || Mem.Size == 512);
225   }
226 
isMemVX32X86Operand227   bool isMemVX32() const {
228     return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
229       getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15;
230   }
isMemVY32X86Operand231   bool isMemVY32() const {
232     return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
233       getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15;
234   }
isMemVX64X86Operand235   bool isMemVX64() const {
236     return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
237       getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15;
238   }
isMemVY64X86Operand239   bool isMemVY64() const {
240     return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
241       getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15;
242   }
isMemVZ32X86Operand243   bool isMemVZ32() const {
244     return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
245       getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31;
246   }
isMemVZ64X86Operand247   bool isMemVZ64() const {
248     return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
249       getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31;
250   }
251 
isAbsMemX86Operand252   bool isAbsMem() const {
253     return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
254       !getMemIndexReg() && getMemScale() == 1;
255   }
256 
isAbsMem16X86Operand257   bool isAbsMem16() const {
258     return isAbsMem() && Mem.ModeSize == 16;
259   }
260 
isAbsMem32X86Operand261   bool isAbsMem32() const {
262     return isAbsMem() && Mem.ModeSize != 16;
263   }
264 
isSrcIdxX86Operand265   bool isSrcIdx() const {
266     return !getMemIndexReg() && getMemScale() == 1 &&
267       (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI ||
268        getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(getMemDisp()) &&
269       cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
270   }
isSrcIdx8X86Operand271   bool isSrcIdx8() const {
272     return isMem8() && isSrcIdx();
273   }
isSrcIdx16X86Operand274   bool isSrcIdx16() const {
275     return isMem16() && isSrcIdx();
276   }
isSrcIdx32X86Operand277   bool isSrcIdx32() const {
278     return isMem32() && isSrcIdx();
279   }
isSrcIdx64X86Operand280   bool isSrcIdx64() const {
281     return isMem64() && isSrcIdx();
282   }
283 
isDstIdxX86Operand284   bool isDstIdx() const {
285     return !getMemIndexReg() && getMemScale() == 1 &&
286       (getMemSegReg() == 0 || getMemSegReg() == X86::ES) &&
287       (getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI ||
288        getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(getMemDisp()) &&
289       cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
290   }
isDstIdx8X86Operand291   bool isDstIdx8() const {
292     return isMem8() && isDstIdx();
293   }
isDstIdx16X86Operand294   bool isDstIdx16() const {
295     return isMem16() && isDstIdx();
296   }
isDstIdx32X86Operand297   bool isDstIdx32() const {
298     return isMem32() && isDstIdx();
299   }
isDstIdx64X86Operand300   bool isDstIdx64() const {
301     return isMem64() && isDstIdx();
302   }
303 
isMemOffsX86Operand304   bool isMemOffs() const {
305     return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() &&
306       getMemScale() == 1;
307   }
308 
isMemOffs16_8X86Operand309   bool isMemOffs16_8() const {
310     return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 8);
311   }
isMemOffs16_16X86Operand312   bool isMemOffs16_16() const {
313     return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 16);
314   }
isMemOffs16_32X86Operand315   bool isMemOffs16_32() const {
316     return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 32);
317   }
isMemOffs32_8X86Operand318   bool isMemOffs32_8() const {
319     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 8);
320   }
isMemOffs32_16X86Operand321   bool isMemOffs32_16() const {
322     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 16);
323   }
isMemOffs32_32X86Operand324   bool isMemOffs32_32() const {
325     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 32);
326   }
isMemOffs32_64X86Operand327   bool isMemOffs32_64() const {
328     return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 64);
329   }
isMemOffs64_8X86Operand330   bool isMemOffs64_8() const {
331     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 8);
332   }
isMemOffs64_16X86Operand333   bool isMemOffs64_16() const {
334     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 16);
335   }
isMemOffs64_32X86Operand336   bool isMemOffs64_32() const {
337     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 32);
338   }
isMemOffs64_64X86Operand339   bool isMemOffs64_64() const {
340     return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 64);
341   }
342 
isRegX86Operand343   bool isReg() const override { return Kind == Register; }
344 
isGR32orGR64X86Operand345   bool isGR32orGR64() const {
346     return Kind == Register &&
347       (X86MCRegisterClasses[X86::GR32RegClassID].contains(getReg()) ||
348       X86MCRegisterClasses[X86::GR64RegClassID].contains(getReg()));
349   }
350 
addExprX86Operand351   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
352     // Add as immediates when possible.
353     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
354       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
355     else
356       Inst.addOperand(MCOperand::CreateExpr(Expr));
357   }
358 
addRegOperandsX86Operand359   void addRegOperands(MCInst &Inst, unsigned N) const {
360     assert(N == 1 && "Invalid number of operands!");
361     Inst.addOperand(MCOperand::CreateReg(getReg()));
362   }
363 
getGR32FromGR64X86Operand364   static unsigned getGR32FromGR64(unsigned RegNo) {
365     switch (RegNo) {
366     default: llvm_unreachable("Unexpected register");
367     case X86::RAX: return X86::EAX;
368     case X86::RCX: return X86::ECX;
369     case X86::RDX: return X86::EDX;
370     case X86::RBX: return X86::EBX;
371     case X86::RBP: return X86::EBP;
372     case X86::RSP: return X86::ESP;
373     case X86::RSI: return X86::ESI;
374     case X86::RDI: return X86::EDI;
375     case X86::R8: return X86::R8D;
376     case X86::R9: return X86::R9D;
377     case X86::R10: return X86::R10D;
378     case X86::R11: return X86::R11D;
379     case X86::R12: return X86::R12D;
380     case X86::R13: return X86::R13D;
381     case X86::R14: return X86::R14D;
382     case X86::R15: return X86::R15D;
383     case X86::RIP: return X86::EIP;
384     }
385   }
386 
addGR32orGR64OperandsX86Operand387   void addGR32orGR64Operands(MCInst &Inst, unsigned N) const {
388     assert(N == 1 && "Invalid number of operands!");
389     unsigned RegNo = getReg();
390     if (X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo))
391       RegNo = getGR32FromGR64(RegNo);
392     Inst.addOperand(MCOperand::CreateReg(RegNo));
393   }
394 
addImmOperandsX86Operand395   void addImmOperands(MCInst &Inst, unsigned N) const {
396     assert(N == 1 && "Invalid number of operands!");
397     addExpr(Inst, getImm());
398   }
399 
addMemOperandsX86Operand400   void addMemOperands(MCInst &Inst, unsigned N) const {
401     assert((N == 5) && "Invalid number of operands!");
402     Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
403     Inst.addOperand(MCOperand::CreateImm(getMemScale()));
404     Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
405     addExpr(Inst, getMemDisp());
406     Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
407   }
408 
addAbsMemOperandsX86Operand409   void addAbsMemOperands(MCInst &Inst, unsigned N) const {
410     assert((N == 1) && "Invalid number of operands!");
411     // Add as immediates when possible.
412     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
413       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
414     else
415       Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
416   }
417 
addSrcIdxOperandsX86Operand418   void addSrcIdxOperands(MCInst &Inst, unsigned N) const {
419     assert((N == 2) && "Invalid number of operands!");
420     Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
421     Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
422   }
addDstIdxOperandsX86Operand423   void addDstIdxOperands(MCInst &Inst, unsigned N) const {
424     assert((N == 1) && "Invalid number of operands!");
425     Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
426   }
427 
addMemOffsOperandsX86Operand428   void addMemOffsOperands(MCInst &Inst, unsigned N) const {
429     assert((N == 2) && "Invalid number of operands!");
430     // Add as immediates when possible.
431     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
432       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
433     else
434       Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
435     Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
436   }
437 
CreateTokenX86Operand438   static std::unique_ptr<X86Operand> CreateToken(StringRef Str, SMLoc Loc) {
439     SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size());
440     auto Res = llvm::make_unique<X86Operand>(Token, Loc, EndLoc);
441     Res->Tok.Data = Str.data();
442     Res->Tok.Length = Str.size();
443     return Res;
444   }
445 
446   static std::unique_ptr<X86Operand>
447   CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
448             bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc(),
449             StringRef SymName = StringRef(), void *OpDecl = nullptr) {
450     auto Res = llvm::make_unique<X86Operand>(Register, StartLoc, EndLoc);
451     Res->Reg.RegNo = RegNo;
452     Res->AddressOf = AddressOf;
453     Res->OffsetOfLoc = OffsetOfLoc;
454     Res->SymName = SymName;
455     Res->OpDecl = OpDecl;
456     return Res;
457   }
458 
CreateImmX86Operand459   static std::unique_ptr<X86Operand> CreateImm(const MCExpr *Val,
460                                                SMLoc StartLoc, SMLoc EndLoc) {
461     auto Res = llvm::make_unique<X86Operand>(Immediate, StartLoc, EndLoc);
462     Res->Imm.Val = Val;
463     return Res;
464   }
465 
466   /// Create an absolute memory operand.
467   static std::unique_ptr<X86Operand>
468   CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc,
469             unsigned Size = 0, StringRef SymName = StringRef(),
470             void *OpDecl = nullptr) {
471     auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
472     Res->Mem.SegReg   = 0;
473     Res->Mem.Disp     = Disp;
474     Res->Mem.BaseReg  = 0;
475     Res->Mem.IndexReg = 0;
476     Res->Mem.Scale    = 1;
477     Res->Mem.Size     = Size;
478     Res->Mem.ModeSize = ModeSize;
479     Res->SymName      = SymName;
480     Res->OpDecl       = OpDecl;
481     Res->AddressOf    = false;
482     return Res;
483   }
484 
485   /// Create a generalized memory operand.
486   static std::unique_ptr<X86Operand>
487   CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp,
488             unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc,
489             SMLoc EndLoc, unsigned Size = 0, StringRef SymName = StringRef(),
490             void *OpDecl = nullptr) {
491     // We should never just have a displacement, that should be parsed as an
492     // absolute memory operand.
493     assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
494 
495     // The scale should always be one of {1,2,4,8}.
496     assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
497            "Invalid scale!");
498     auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
499     Res->Mem.SegReg   = SegReg;
500     Res->Mem.Disp     = Disp;
501     Res->Mem.BaseReg  = BaseReg;
502     Res->Mem.IndexReg = IndexReg;
503     Res->Mem.Scale    = Scale;
504     Res->Mem.Size     = Size;
505     Res->Mem.ModeSize = ModeSize;
506     Res->SymName      = SymName;
507     Res->OpDecl       = OpDecl;
508     Res->AddressOf    = false;
509     return Res;
510   }
511 };
512 
513 } // End of namespace llvm
514 
515 #endif
516