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 //===----------------------------------------------------------------------===//
13 #include "X86AsmParserCommon.h"
14 #include "llvm/MC/MCExpr.h"
15 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
19 /// X86Operand - Instances of this class represent a parsed X86 machine
21 struct X86Operand : public MCParsedAsmOperand {
29 SMLoc StartLoc, EndLoc;
64 X86Operand(KindTy K, SMLoc Start, SMLoc End)
65 : Kind(K), StartLoc(Start), EndLoc(End) {}
67 StringRef getSymName() override { return SymName; }
68 void *getOpDecl() override { return OpDecl; }
70 /// getStartLoc - Get the location of the first token of this operand.
71 SMLoc getStartLoc() const override { return StartLoc; }
72 /// getEndLoc - Get the location of the last token of this operand.
73 SMLoc getEndLoc() const override { return EndLoc; }
74 /// getLocRange - Get the range between the first and last token of this
76 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
77 /// getOffsetOfLoc - Get the location of the offset operator.
78 SMLoc getOffsetOfLoc() const override { return OffsetOfLoc; }
80 void print(raw_ostream &OS) const override {}
82 StringRef getToken() const {
83 assert(Kind == Token && "Invalid access!");
84 return StringRef(Tok.Data, Tok.Length);
86 void setTokenValue(StringRef Value) {
87 assert(Kind == Token && "Invalid access!");
88 Tok.Data = Value.data();
89 Tok.Length = Value.size();
92 unsigned getReg() const override {
93 assert(Kind == Register && "Invalid access!");
97 const MCExpr *getImm() const {
98 assert(Kind == Immediate && "Invalid access!");
102 const MCExpr *getMemDisp() const {
103 assert(Kind == Memory && "Invalid access!");
106 unsigned getMemSegReg() const {
107 assert(Kind == Memory && "Invalid access!");
110 unsigned getMemBaseReg() const {
111 assert(Kind == Memory && "Invalid access!");
114 unsigned getMemIndexReg() const {
115 assert(Kind == Memory && "Invalid access!");
118 unsigned getMemScale() const {
119 assert(Kind == Memory && "Invalid access!");
123 bool isToken() const override {return Kind == Token; }
125 bool isImm() const override { return Kind == Immediate; }
127 bool isImmSExti16i8() const {
131 // If this isn't a constant expr, just assume it fits and let relaxation
133 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
137 // Otherwise, check the value is in a range that makes sense for this
139 return isImmSExti16i8Value(CE->getValue());
141 bool isImmSExti32i8() const {
145 // If this isn't a constant expr, just assume it fits and let relaxation
147 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
151 // Otherwise, check the value is in a range that makes sense for this
153 return isImmSExti32i8Value(CE->getValue());
155 bool isImmZExtu32u8() const {
159 // If this isn't a constant expr, just assume it fits and let relaxation
161 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
165 // Otherwise, check the value is in a range that makes sense for this
167 return isImmZExtu32u8Value(CE->getValue());
169 bool isImmSExti64i8() const {
173 // If this isn't a constant expr, just assume it fits and let relaxation
175 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
179 // Otherwise, check the value is in a range that makes sense for this
181 return isImmSExti64i8Value(CE->getValue());
183 bool isImmSExti64i32() const {
187 // If this isn't a constant expr, just assume it fits and let relaxation
189 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
193 // Otherwise, check the value is in a range that makes sense for this
195 return isImmSExti64i32Value(CE->getValue());
198 bool isOffsetOf() const override {
199 return OffsetOfLoc.getPointer();
202 bool needAddressOf() const override {
206 bool isMem() const override { return Kind == Memory; }
207 bool isMem8() const {
208 return Kind == Memory && (!Mem.Size || Mem.Size == 8);
210 bool isMem16() const {
211 return Kind == Memory && (!Mem.Size || Mem.Size == 16);
213 bool isMem32() const {
214 return Kind == Memory && (!Mem.Size || Mem.Size == 32);
216 bool isMem64() const {
217 return Kind == Memory && (!Mem.Size || Mem.Size == 64);
219 bool isMem80() const {
220 return Kind == Memory && (!Mem.Size || Mem.Size == 80);
222 bool isMem128() const {
223 return Kind == Memory && (!Mem.Size || Mem.Size == 128);
225 bool isMem256() const {
226 return Kind == Memory && (!Mem.Size || Mem.Size == 256);
228 bool isMem512() const {
229 return Kind == Memory && (!Mem.Size || Mem.Size == 512);
232 bool isMemVX32() const {
233 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
234 getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15;
236 bool isMemVY32() const {
237 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
238 getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15;
240 bool isMemVX64() const {
241 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
242 getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15;
244 bool isMemVY64() const {
245 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
246 getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15;
248 bool isMemVZ32() const {
249 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
250 getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31;
252 bool isMemVZ64() const {
253 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
254 getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31;
257 bool isAbsMem() const {
258 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
259 !getMemIndexReg() && getMemScale() == 1;
262 bool isSrcIdx() const {
263 return !getMemIndexReg() && getMemScale() == 1 &&
264 (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI ||
265 getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(getMemDisp()) &&
266 cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
268 bool isSrcIdx8() const {
269 return isMem8() && isSrcIdx();
271 bool isSrcIdx16() const {
272 return isMem16() && isSrcIdx();
274 bool isSrcIdx32() const {
275 return isMem32() && isSrcIdx();
277 bool isSrcIdx64() const {
278 return isMem64() && isSrcIdx();
281 bool isDstIdx() const {
282 return !getMemIndexReg() && getMemScale() == 1 &&
283 (getMemSegReg() == 0 || getMemSegReg() == X86::ES) &&
284 (getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI ||
285 getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(getMemDisp()) &&
286 cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
288 bool isDstIdx8() const {
289 return isMem8() && isDstIdx();
291 bool isDstIdx16() const {
292 return isMem16() && isDstIdx();
294 bool isDstIdx32() const {
295 return isMem32() && isDstIdx();
297 bool isDstIdx64() const {
298 return isMem64() && isDstIdx();
301 bool isMemOffs8() const {
302 return Kind == Memory && !getMemBaseReg() &&
303 !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 8);
305 bool isMemOffs16() const {
306 return Kind == Memory && !getMemBaseReg() &&
307 !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 16);
309 bool isMemOffs32() const {
310 return Kind == Memory && !getMemBaseReg() &&
311 !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 32);
313 bool isMemOffs64() const {
314 return Kind == Memory && !getMemBaseReg() &&
315 !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 64);
318 bool isReg() const override { return Kind == Register; }
320 bool isGR32orGR64() const {
321 return Kind == Register &&
322 (X86MCRegisterClasses[X86::GR32RegClassID].contains(getReg()) ||
323 X86MCRegisterClasses[X86::GR64RegClassID].contains(getReg()));
326 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
327 // Add as immediates when possible.
328 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
329 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
331 Inst.addOperand(MCOperand::CreateExpr(Expr));
334 void addRegOperands(MCInst &Inst, unsigned N) const {
335 assert(N == 1 && "Invalid number of operands!");
336 Inst.addOperand(MCOperand::CreateReg(getReg()));
339 static unsigned getGR32FromGR64(unsigned RegNo) {
341 default: llvm_unreachable("Unexpected register");
342 case X86::RAX: return X86::EAX;
343 case X86::RCX: return X86::ECX;
344 case X86::RDX: return X86::EDX;
345 case X86::RBX: return X86::EBX;
346 case X86::RBP: return X86::EBP;
347 case X86::RSP: return X86::ESP;
348 case X86::RSI: return X86::ESI;
349 case X86::RDI: return X86::EDI;
350 case X86::R8: return X86::R8D;
351 case X86::R9: return X86::R9D;
352 case X86::R10: return X86::R10D;
353 case X86::R11: return X86::R11D;
354 case X86::R12: return X86::R12D;
355 case X86::R13: return X86::R13D;
356 case X86::R14: return X86::R14D;
357 case X86::R15: return X86::R15D;
358 case X86::RIP: return X86::EIP;
362 void addGR32orGR64Operands(MCInst &Inst, unsigned N) const {
363 assert(N == 1 && "Invalid number of operands!");
364 unsigned RegNo = getReg();
365 if (X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo))
366 RegNo = getGR32FromGR64(RegNo);
367 Inst.addOperand(MCOperand::CreateReg(RegNo));
370 void addImmOperands(MCInst &Inst, unsigned N) const {
371 assert(N == 1 && "Invalid number of operands!");
372 addExpr(Inst, getImm());
375 void addMemOperands(MCInst &Inst, unsigned N) const {
376 assert((N == 5) && "Invalid number of operands!");
377 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
378 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
379 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
380 addExpr(Inst, getMemDisp());
381 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
384 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
385 assert((N == 1) && "Invalid number of operands!");
386 // Add as immediates when possible.
387 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
388 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
390 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
393 void addSrcIdxOperands(MCInst &Inst, unsigned N) const {
394 assert((N == 2) && "Invalid number of operands!");
395 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
396 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
398 void addDstIdxOperands(MCInst &Inst, unsigned N) const {
399 assert((N == 1) && "Invalid number of operands!");
400 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
403 void addMemOffsOperands(MCInst &Inst, unsigned N) const {
404 assert((N == 2) && "Invalid number of operands!");
405 // Add as immediates when possible.
406 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
407 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
409 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
410 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
413 static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
414 SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size());
415 X86Operand *Res = new X86Operand(Token, Loc, EndLoc);
416 Res->Tok.Data = Str.data();
417 Res->Tok.Length = Str.size();
421 static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
422 bool AddressOf = false,
423 SMLoc OffsetOfLoc = SMLoc(),
424 StringRef SymName = StringRef(),
426 X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
427 Res->Reg.RegNo = RegNo;
428 Res->AddressOf = AddressOf;
429 Res->OffsetOfLoc = OffsetOfLoc;
430 Res->SymName = SymName;
431 Res->OpDecl = OpDecl;
435 static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
436 X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
441 /// Create an absolute memory operand.
442 static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc,
443 unsigned Size = 0, StringRef SymName = StringRef(),
445 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
447 Res->Mem.Disp = Disp;
448 Res->Mem.BaseReg = 0;
449 Res->Mem.IndexReg = 0;
451 Res->Mem.Size = Size;
452 Res->SymName = SymName;
453 Res->OpDecl = OpDecl;
454 Res->AddressOf = false;
458 /// Create a generalized memory operand.
459 static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
460 unsigned BaseReg, unsigned IndexReg,
461 unsigned Scale, SMLoc StartLoc, SMLoc EndLoc,
463 StringRef SymName = StringRef(),
465 // We should never just have a displacement, that should be parsed as an
466 // absolute memory operand.
467 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
469 // The scale should always be one of {1,2,4,8}.
470 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
472 X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
473 Res->Mem.SegReg = SegReg;
474 Res->Mem.Disp = Disp;
475 Res->Mem.BaseReg = BaseReg;
476 Res->Mem.IndexReg = IndexReg;
477 Res->Mem.Scale = Scale;
478 Res->Mem.Size = Size;
479 Res->SymName = SymName;
480 Res->OpDecl = OpDecl;
481 Res->AddressOf = false;
486 } // End of namespace llvm
488 #endif // X86_OPERAND