blob: 11a84157f58c172e9bef97b79d16815f40f4ef84 [file] [log] [blame]
Evgeniy Stepanove3804d42014-02-28 12:28:07 +00001//===-- 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
Benjamin Kramera7c40ef2014-08-13 16:26:38 +000010#ifndef LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
11#define LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
Evgeniy Stepanove3804d42014-02-28 12:28:07 +000012
13#include "X86AsmParserCommon.h"
14#include "llvm/MC/MCExpr.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
David Blaikie960ea3f2014-06-08 16:18:35 +000016#include "llvm/ADT/STLExtras.h"
Evgeniy Stepanove3804d42014-02-28 12:28:07 +000017
18namespace llvm {
19
20/// X86Operand - Instances of this class represent a parsed X86 machine
21/// instruction.
22struct 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 };
57
58 union {
59 struct TokOp Tok;
60 struct RegOp Reg;
61 struct ImmOp Imm;
62 struct MemOp Mem;
63 };
64
65 X86Operand(KindTy K, SMLoc Start, SMLoc End)
66 : Kind(K), StartLoc(Start), EndLoc(End) {}
67
Craig Topper39012cc2014-03-09 18:03:14 +000068 StringRef getSymName() override { return SymName; }
69 void *getOpDecl() override { return OpDecl; }
Evgeniy Stepanove3804d42014-02-28 12:28:07 +000070
71 /// getStartLoc - Get the location of the first token of this operand.
Craig Topper39012cc2014-03-09 18:03:14 +000072 SMLoc getStartLoc() const override { return StartLoc; }
Evgeniy Stepanove3804d42014-02-28 12:28:07 +000073 /// getEndLoc - Get the location of the last token of this operand.
Craig Topper39012cc2014-03-09 18:03:14 +000074 SMLoc getEndLoc() const override { return EndLoc; }
Evgeniy Stepanove3804d42014-02-28 12:28:07 +000075 /// getLocRange - Get the range between the first and last token of this
76 /// operand.
77 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
78 /// getOffsetOfLoc - Get the location of the offset operator.
Craig Topper39012cc2014-03-09 18:03:14 +000079 SMLoc getOffsetOfLoc() const override { return OffsetOfLoc; }
Evgeniy Stepanove3804d42014-02-28 12:28:07 +000080
Craig Topper39012cc2014-03-09 18:03:14 +000081 void print(raw_ostream &OS) const override {}
Evgeniy Stepanove3804d42014-02-28 12:28:07 +000082
83 StringRef getToken() const {
84 assert(Kind == Token && "Invalid access!");
85 return StringRef(Tok.Data, Tok.Length);
86 }
87 void setTokenValue(StringRef Value) {
88 assert(Kind == Token && "Invalid access!");
89 Tok.Data = Value.data();
90 Tok.Length = Value.size();
91 }
92
Craig Topper39012cc2014-03-09 18:03:14 +000093 unsigned getReg() const override {
Evgeniy Stepanove3804d42014-02-28 12:28:07 +000094 assert(Kind == Register && "Invalid access!");
95 return Reg.RegNo;
96 }
97
98 const MCExpr *getImm() const {
99 assert(Kind == Immediate && "Invalid access!");
100 return Imm.Val;
101 }
102
103 const MCExpr *getMemDisp() const {
104 assert(Kind == Memory && "Invalid access!");
105 return Mem.Disp;
106 }
107 unsigned getMemSegReg() const {
108 assert(Kind == Memory && "Invalid access!");
109 return Mem.SegReg;
110 }
111 unsigned getMemBaseReg() const {
112 assert(Kind == Memory && "Invalid access!");
113 return Mem.BaseReg;
114 }
115 unsigned getMemIndexReg() const {
116 assert(Kind == Memory && "Invalid access!");
117 return Mem.IndexReg;
118 }
119 unsigned getMemScale() const {
120 assert(Kind == Memory && "Invalid access!");
121 return Mem.Scale;
122 }
123
Craig Topper39012cc2014-03-09 18:03:14 +0000124 bool isToken() const override {return Kind == Token; }
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000125
Craig Topper39012cc2014-03-09 18:03:14 +0000126 bool isImm() const override { return Kind == Immediate; }
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000127
128 bool isImmSExti16i8() const {
129 if (!isImm())
130 return false;
131
132 // If this isn't a constant expr, just assume it fits and let relaxation
133 // handle it.
134 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
135 if (!CE)
136 return true;
137
138 // Otherwise, check the value is in a range that makes sense for this
139 // extension.
140 return isImmSExti16i8Value(CE->getValue());
141 }
142 bool isImmSExti32i8() const {
143 if (!isImm())
144 return false;
145
146 // If this isn't a constant expr, just assume it fits and let relaxation
147 // handle it.
148 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
149 if (!CE)
150 return true;
151
152 // Otherwise, check the value is in a range that makes sense for this
153 // extension.
154 return isImmSExti32i8Value(CE->getValue());
155 }
156 bool isImmZExtu32u8() const {
157 if (!isImm())
158 return false;
159
160 // If this isn't a constant expr, just assume it fits and let relaxation
161 // handle it.
162 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
163 if (!CE)
164 return true;
165
166 // Otherwise, check the value is in a range that makes sense for this
167 // extension.
168 return isImmZExtu32u8Value(CE->getValue());
169 }
170 bool isImmSExti64i8() const {
171 if (!isImm())
172 return false;
173
174 // If this isn't a constant expr, just assume it fits and let relaxation
175 // handle it.
176 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
177 if (!CE)
178 return true;
179
180 // Otherwise, check the value is in a range that makes sense for this
181 // extension.
182 return isImmSExti64i8Value(CE->getValue());
183 }
184 bool isImmSExti64i32() const {
185 if (!isImm())
186 return false;
187
188 // If this isn't a constant expr, just assume it fits and let relaxation
189 // handle it.
190 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
191 if (!CE)
192 return true;
193
194 // Otherwise, check the value is in a range that makes sense for this
195 // extension.
196 return isImmSExti64i32Value(CE->getValue());
197 }
198
Craig Topper39012cc2014-03-09 18:03:14 +0000199 bool isOffsetOf() const override {
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000200 return OffsetOfLoc.getPointer();
201 }
202
Craig Topper39012cc2014-03-09 18:03:14 +0000203 bool needAddressOf() const override {
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000204 return AddressOf;
205 }
206
Craig Topper39012cc2014-03-09 18:03:14 +0000207 bool isMem() const override { return Kind == Memory; }
Reid Klecknerf6fb7802014-08-26 20:32:34 +0000208 bool isMemUnsized() const {
209 return Kind == Memory && Mem.Size == 0;
210 }
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000211 bool isMem8() const {
212 return Kind == Memory && (!Mem.Size || Mem.Size == 8);
213 }
214 bool isMem16() const {
215 return Kind == Memory && (!Mem.Size || Mem.Size == 16);
216 }
217 bool isMem32() const {
218 return Kind == Memory && (!Mem.Size || Mem.Size == 32);
219 }
220 bool isMem64() const {
221 return Kind == Memory && (!Mem.Size || Mem.Size == 64);
222 }
223 bool isMem80() const {
224 return Kind == Memory && (!Mem.Size || Mem.Size == 80);
225 }
226 bool isMem128() const {
227 return Kind == Memory && (!Mem.Size || Mem.Size == 128);
228 }
229 bool isMem256() const {
230 return Kind == Memory && (!Mem.Size || Mem.Size == 256);
231 }
232 bool isMem512() const {
233 return Kind == Memory && (!Mem.Size || Mem.Size == 512);
234 }
235
236 bool isMemVX32() const {
237 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
238 getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15;
239 }
240 bool isMemVY32() const {
241 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
242 getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15;
243 }
244 bool isMemVX64() const {
245 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
246 getMemIndexReg() >= X86::XMM0 && getMemIndexReg() <= X86::XMM15;
247 }
248 bool isMemVY64() const {
249 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
250 getMemIndexReg() >= X86::YMM0 && getMemIndexReg() <= X86::YMM15;
251 }
252 bool isMemVZ32() const {
253 return Kind == Memory && (!Mem.Size || Mem.Size == 32) &&
254 getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31;
255 }
256 bool isMemVZ64() const {
257 return Kind == Memory && (!Mem.Size || Mem.Size == 64) &&
258 getMemIndexReg() >= X86::ZMM0 && getMemIndexReg() <= X86::ZMM31;
259 }
260
261 bool isAbsMem() const {
262 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
263 !getMemIndexReg() && getMemScale() == 1;
264 }
265
266 bool isSrcIdx() const {
267 return !getMemIndexReg() && getMemScale() == 1 &&
268 (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI ||
269 getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(getMemDisp()) &&
270 cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
271 }
272 bool isSrcIdx8() const {
273 return isMem8() && isSrcIdx();
274 }
275 bool isSrcIdx16() const {
276 return isMem16() && isSrcIdx();
277 }
278 bool isSrcIdx32() const {
279 return isMem32() && isSrcIdx();
280 }
281 bool isSrcIdx64() const {
282 return isMem64() && isSrcIdx();
283 }
284
285 bool isDstIdx() const {
286 return !getMemIndexReg() && getMemScale() == 1 &&
287 (getMemSegReg() == 0 || getMemSegReg() == X86::ES) &&
288 (getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI ||
289 getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(getMemDisp()) &&
290 cast<MCConstantExpr>(getMemDisp())->getValue() == 0;
291 }
292 bool isDstIdx8() const {
293 return isMem8() && isDstIdx();
294 }
295 bool isDstIdx16() const {
296 return isMem16() && isDstIdx();
297 }
298 bool isDstIdx32() const {
299 return isMem32() && isDstIdx();
300 }
301 bool isDstIdx64() const {
302 return isMem64() && isDstIdx();
303 }
304
305 bool isMemOffs8() const {
306 return Kind == Memory && !getMemBaseReg() &&
307 !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 8);
308 }
309 bool isMemOffs16() const {
310 return Kind == Memory && !getMemBaseReg() &&
311 !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 16);
312 }
313 bool isMemOffs32() const {
314 return Kind == Memory && !getMemBaseReg() &&
315 !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 32);
316 }
317 bool isMemOffs64() const {
318 return Kind == Memory && !getMemBaseReg() &&
319 !getMemIndexReg() && getMemScale() == 1 && (!Mem.Size || Mem.Size == 64);
320 }
321
Craig Topper39012cc2014-03-09 18:03:14 +0000322 bool isReg() const override { return Kind == Register; }
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000323
324 bool isGR32orGR64() const {
325 return Kind == Register &&
326 (X86MCRegisterClasses[X86::GR32RegClassID].contains(getReg()) ||
327 X86MCRegisterClasses[X86::GR64RegClassID].contains(getReg()));
328 }
329
330 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
331 // Add as immediates when possible.
332 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
333 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
334 else
335 Inst.addOperand(MCOperand::CreateExpr(Expr));
336 }
337
338 void addRegOperands(MCInst &Inst, unsigned N) const {
339 assert(N == 1 && "Invalid number of operands!");
340 Inst.addOperand(MCOperand::CreateReg(getReg()));
341 }
342
343 static unsigned getGR32FromGR64(unsigned RegNo) {
344 switch (RegNo) {
345 default: llvm_unreachable("Unexpected register");
346 case X86::RAX: return X86::EAX;
347 case X86::RCX: return X86::ECX;
348 case X86::RDX: return X86::EDX;
349 case X86::RBX: return X86::EBX;
350 case X86::RBP: return X86::EBP;
351 case X86::RSP: return X86::ESP;
352 case X86::RSI: return X86::ESI;
353 case X86::RDI: return X86::EDI;
354 case X86::R8: return X86::R8D;
355 case X86::R9: return X86::R9D;
356 case X86::R10: return X86::R10D;
357 case X86::R11: return X86::R11D;
358 case X86::R12: return X86::R12D;
359 case X86::R13: return X86::R13D;
360 case X86::R14: return X86::R14D;
361 case X86::R15: return X86::R15D;
362 case X86::RIP: return X86::EIP;
363 }
364 }
365
366 void addGR32orGR64Operands(MCInst &Inst, unsigned N) const {
367 assert(N == 1 && "Invalid number of operands!");
368 unsigned RegNo = getReg();
369 if (X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo))
370 RegNo = getGR32FromGR64(RegNo);
371 Inst.addOperand(MCOperand::CreateReg(RegNo));
372 }
373
374 void addImmOperands(MCInst &Inst, unsigned N) const {
375 assert(N == 1 && "Invalid number of operands!");
376 addExpr(Inst, getImm());
377 }
378
379 void addMemOperands(MCInst &Inst, unsigned N) const {
380 assert((N == 5) && "Invalid number of operands!");
381 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
382 Inst.addOperand(MCOperand::CreateImm(getMemScale()));
383 Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
384 addExpr(Inst, getMemDisp());
385 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
386 }
387
388 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
389 assert((N == 1) && "Invalid number of operands!");
390 // Add as immediates when possible.
391 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
392 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
393 else
394 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
395 }
396
397 void addSrcIdxOperands(MCInst &Inst, unsigned N) const {
398 assert((N == 2) && "Invalid number of operands!");
399 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
400 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
401 }
402 void addDstIdxOperands(MCInst &Inst, unsigned N) const {
403 assert((N == 1) && "Invalid number of operands!");
404 Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
405 }
406
407 void addMemOffsOperands(MCInst &Inst, unsigned N) const {
408 assert((N == 2) && "Invalid number of operands!");
409 // Add as immediates when possible.
410 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemDisp()))
411 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
412 else
413 Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
414 Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
415 }
416
David Blaikie960ea3f2014-06-08 16:18:35 +0000417 static std::unique_ptr<X86Operand> CreateToken(StringRef Str, SMLoc Loc) {
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000418 SMLoc EndLoc = SMLoc::getFromPointer(Loc.getPointer() + Str.size());
David Blaikie960ea3f2014-06-08 16:18:35 +0000419 auto Res = llvm::make_unique<X86Operand>(Token, Loc, EndLoc);
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000420 Res->Tok.Data = Str.data();
421 Res->Tok.Length = Str.size();
422 return Res;
423 }
424
David Blaikie960ea3f2014-06-08 16:18:35 +0000425 static std::unique_ptr<X86Operand>
426 CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
427 bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc(),
428 StringRef SymName = StringRef(), void *OpDecl = nullptr) {
429 auto Res = llvm::make_unique<X86Operand>(Register, StartLoc, EndLoc);
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000430 Res->Reg.RegNo = RegNo;
431 Res->AddressOf = AddressOf;
432 Res->OffsetOfLoc = OffsetOfLoc;
433 Res->SymName = SymName;
434 Res->OpDecl = OpDecl;
435 return Res;
436 }
437
David Blaikie960ea3f2014-06-08 16:18:35 +0000438 static std::unique_ptr<X86Operand> CreateImm(const MCExpr *Val,
439 SMLoc StartLoc, SMLoc EndLoc) {
440 auto Res = llvm::make_unique<X86Operand>(Immediate, StartLoc, EndLoc);
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000441 Res->Imm.Val = Val;
442 return Res;
443 }
444
445 /// Create an absolute memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +0000446 static std::unique_ptr<X86Operand>
447 CreateMem(const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc, unsigned Size = 0,
448 StringRef SymName = StringRef(), void *OpDecl = nullptr) {
449 auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000450 Res->Mem.SegReg = 0;
451 Res->Mem.Disp = Disp;
452 Res->Mem.BaseReg = 0;
453 Res->Mem.IndexReg = 0;
454 Res->Mem.Scale = 1;
455 Res->Mem.Size = Size;
456 Res->SymName = SymName;
457 Res->OpDecl = OpDecl;
458 Res->AddressOf = false;
459 return Res;
460 }
461
462 /// Create a generalized memory operand.
David Blaikie960ea3f2014-06-08 16:18:35 +0000463 static std::unique_ptr<X86Operand>
464 CreateMem(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg,
465 unsigned IndexReg, unsigned Scale, SMLoc StartLoc, SMLoc EndLoc,
466 unsigned Size = 0, StringRef SymName = StringRef(),
467 void *OpDecl = nullptr) {
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000468 // We should never just have a displacement, that should be parsed as an
469 // absolute memory operand.
470 assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
471
472 // The scale should always be one of {1,2,4,8}.
473 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
474 "Invalid scale!");
David Blaikie960ea3f2014-06-08 16:18:35 +0000475 auto Res = llvm::make_unique<X86Operand>(Memory, StartLoc, EndLoc);
Evgeniy Stepanove3804d42014-02-28 12:28:07 +0000476 Res->Mem.SegReg = SegReg;
477 Res->Mem.Disp = Disp;
478 Res->Mem.BaseReg = BaseReg;
479 Res->Mem.IndexReg = IndexReg;
480 Res->Mem.Scale = Scale;
481 Res->Mem.Size = Size;
482 Res->SymName = SymName;
483 Res->OpDecl = OpDecl;
484 Res->AddressOf = false;
485 return Res;
486 }
487};
488
489} // End of namespace llvm
490
Benjamin Kramera7c40ef2014-08-13 16:26:38 +0000491#endif