1//===- X86Operand.h - Parsed X86 machine instruction ------------*- C++ -*-===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
9#ifndef LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
10#define LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
11
12#include "MCTargetDesc/X86IntelInstPrinter.h"
13#include "MCTargetDesc/X86MCTargetDesc.h"
14#include "X86AsmParserCommon.h"
15#include "llvm/ADT/STLExtras.h"
16#include "llvm/ADT/StringRef.h"
17#include "llvm/MC/MCExpr.h"
18#include "llvm/MC/MCInst.h"
19#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
20#include "llvm/MC/MCRegisterInfo.h"
21#include "llvm/MC/MCSymbol.h"
22#include "llvm/Support/Casting.h"
23#include "llvm/Support/SMLoc.h"
24#include <cassert>
25#include <memory>
26
27namespace llvm {
28
29/// X86Operand - Instances of this class represent a parsed X86 machine
30/// instruction.
31struct X86Operand final : public MCParsedAsmOperand {
32 enum KindTy { Token, Register, Immediate, Memory, Prefix, DXRegister } Kind;
33
34 SMLoc StartLoc, EndLoc;
35 SMLoc OffsetOfLoc;
36 StringRef SymName;
37 void *OpDecl;
38 bool AddressOf;
39
40 /// This used for inline asm which may specify base reg and index reg for
41 /// MemOp. e.g. ARR[eax + ecx*4], so no extra reg can be used for MemOp.
42 bool UseUpRegs = false;
43
44 struct TokOp {
45 const char *Data;
46 unsigned Length;
47 };
48
49 struct RegOp {
50 unsigned RegNo;
51 };
52
53 struct PrefOp {
54 unsigned Prefixes;
55 };
56
57 struct ImmOp {
58 const MCExpr *Val;
59 bool LocalRef;
60 };
61
62 struct MemOp {
63 unsigned SegReg;
64 const MCExpr *Disp;
65 unsigned BaseReg;
66 unsigned DefaultBaseReg;
67 unsigned IndexReg;
68 unsigned Scale;
69 unsigned Size;
70 unsigned ModeSize;
71
72 /// If the memory operand is unsized and there are multiple instruction
73 /// matches, prefer the one with this size.
74 unsigned FrontendSize;
75
76 /// If false, then this operand must be a memory operand for an indirect
77 /// branch instruction. Otherwise, this operand may belong to either a
78 /// direct or indirect branch instruction.
79 bool MaybeDirectBranchDest;
80 };
81
82 union {
83 struct TokOp Tok;
84 struct RegOp Reg;
85 struct ImmOp Imm;
86 struct MemOp Mem;
87 struct PrefOp Pref;
88 };
89
90 X86Operand(KindTy K, SMLoc Start, SMLoc End)
91 : Kind(K), StartLoc(Start), EndLoc(End), OpDecl(nullptr),
92 AddressOf(false) {}
93
94 StringRef getSymName() override { return SymName; }
95 void *getOpDecl() override { return OpDecl; }
96
97 /// getStartLoc - Get the location of the first token of this operand.
98 SMLoc getStartLoc() const override { return StartLoc; }
99
100 /// getEndLoc - Get the location of the last token of this operand.
101 SMLoc getEndLoc() const override { return EndLoc; }
102
103 /// getLocRange - Get the range between the first and last token of this
104 /// operand.
105 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
106
107 /// getOffsetOfLoc - Get the location of the offset operator.
108 SMLoc getOffsetOfLoc() const override { return OffsetOfLoc; }
109
110 void print(raw_ostream &OS) const override {
111
112 auto PrintImmValue = [&](const MCExpr *Val, const char *VName) {
113 if (Val->getKind() == MCExpr::Constant) {
114 if (auto Imm = cast<MCConstantExpr>(Val)->getValue())
115 OS << VName << Imm;
116 } else if (Val->getKind() == MCExpr::SymbolRef) {
117 if (auto *SRE = dyn_cast<MCSymbolRefExpr>(Val)) {
118 const MCSymbol &Sym = SRE->getSymbol();
119 if (const char *SymNameStr = Sym.getName().data())
120 OS << VName << SymNameStr;
121 }
122 }
123 };
124
125 switch (Kind) {
126 case Token:
127 OS << Tok.Data;
128 break;
129 case Register:
130 OS << "Reg:" << X86IntelInstPrinter::getRegisterName(Reg: Reg.RegNo);
131 break;
132 case DXRegister:
133 OS << "DXReg";
134 break;
135 case Immediate:
136 PrintImmValue(Imm.Val, "Imm:");
137 break;
138 case Prefix:
139 OS << "Prefix:" << Pref.Prefixes;
140 break;
141 case Memory:
142 OS << "Memory: ModeSize=" << Mem.ModeSize;
143 if (Mem.Size)
144 OS << ",Size=" << Mem.Size;
145 if (Mem.BaseReg)
146 OS << ",BaseReg=" << X86IntelInstPrinter::getRegisterName(Reg: Mem.BaseReg);
147 if (Mem.IndexReg)
148 OS << ",IndexReg="
149 << X86IntelInstPrinter::getRegisterName(Reg: Mem.IndexReg);
150 if (Mem.Scale)
151 OS << ",Scale=" << Mem.Scale;
152 if (Mem.Disp)
153 PrintImmValue(Mem.Disp, ",Disp=");
154 if (Mem.SegReg)
155 OS << ",SegReg=" << X86IntelInstPrinter::getRegisterName(Reg: Mem.SegReg);
156 break;
157 }
158 }
159
160 StringRef getToken() const {
161 assert(Kind == Token && "Invalid access!");
162 return StringRef(Tok.Data, Tok.Length);
163 }
164 void setTokenValue(StringRef Value) {
165 assert(Kind == Token && "Invalid access!");
166 Tok.Data = Value.data();
167 Tok.Length = Value.size();
168 }
169
170 MCRegister getReg() const override {
171 assert(Kind == Register && "Invalid access!");
172 return Reg.RegNo;
173 }
174
175 unsigned getPrefix() const {
176 assert(Kind == Prefix && "Invalid access!");
177 return Pref.Prefixes;
178 }
179
180 const MCExpr *getImm() const {
181 assert(Kind == Immediate && "Invalid access!");
182 return Imm.Val;
183 }
184
185 const MCExpr *getMemDisp() const {
186 assert(Kind == Memory && "Invalid access!");
187 return Mem.Disp;
188 }
189 unsigned getMemSegReg() const {
190 assert(Kind == Memory && "Invalid access!");
191 return Mem.SegReg;
192 }
193 unsigned getMemBaseReg() const {
194 assert(Kind == Memory && "Invalid access!");
195 return Mem.BaseReg;
196 }
197 unsigned getMemDefaultBaseReg() const {
198 assert(Kind == Memory && "Invalid access!");
199 return Mem.DefaultBaseReg;
200 }
201 unsigned getMemIndexReg() const {
202 assert(Kind == Memory && "Invalid access!");
203 return Mem.IndexReg;
204 }
205 unsigned getMemScale() const {
206 assert(Kind == Memory && "Invalid access!");
207 return Mem.Scale;
208 }
209 unsigned getMemModeSize() const {
210 assert(Kind == Memory && "Invalid access!");
211 return Mem.ModeSize;
212 }
213 unsigned getMemFrontendSize() const {
214 assert(Kind == Memory && "Invalid access!");
215 return Mem.FrontendSize;
216 }
217 bool isMaybeDirectBranchDest() const {
218 assert(Kind == Memory && "Invalid access!");
219 return Mem.MaybeDirectBranchDest;
220 }
221
222 bool isToken() const override {return Kind == Token; }
223
224 bool isImm() const override { return Kind == Immediate; }
225
226 bool isImmSExti16i8() const {
227 if (!isImm())
228 return false;
229
230 // If this isn't a constant expr, just assume it fits and let relaxation
231 // handle it.
232 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getImm());
233 if (!CE)
234 return true;
235
236 // Otherwise, check the value is in a range that makes sense for this
237 // extension.
238 return isImmSExti16i8Value(Value: CE->getValue());
239 }
240 bool isImmSExti32i8() const {
241 if (!isImm())
242 return false;
243
244 // If this isn't a constant expr, just assume it fits and let relaxation
245 // handle it.
246 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getImm());
247 if (!CE)
248 return true;
249
250 // Otherwise, check the value is in a range that makes sense for this
251 // extension.
252 return isImmSExti32i8Value(Value: CE->getValue());
253 }
254 bool isImmSExti64i8() const {
255 if (!isImm())
256 return false;
257
258 // If this isn't a constant expr, just assume it fits and let relaxation
259 // handle it.
260 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getImm());
261 if (!CE)
262 return true;
263
264 // Otherwise, check the value is in a range that makes sense for this
265 // extension.
266 return isImmSExti64i8Value(Value: CE->getValue());
267 }
268 bool isImmSExti64i32() const {
269 if (!isImm())
270 return false;
271
272 // If this isn't a constant expr, just assume it fits and let relaxation
273 // handle it.
274 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getImm());
275 if (!CE)
276 return true;
277
278 // Otherwise, check the value is in a range that makes sense for this
279 // extension.
280 return isImmSExti64i32Value(Value: CE->getValue());
281 }
282
283 bool isImmUnsignedi4() const {
284 if (!isImm()) return false;
285 // If this isn't a constant expr, reject it. The immediate byte is shared
286 // with a register encoding. We can't have it affected by a relocation.
287 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getImm());
288 if (!CE) return false;
289 return isImmUnsignedi4Value(Value: CE->getValue());
290 }
291
292 bool isImmUnsignedi8() const {
293 if (!isImm()) return false;
294 // If this isn't a constant expr, just assume it fits and let relaxation
295 // handle it.
296 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getImm());
297 if (!CE) return true;
298 return isImmUnsignedi8Value(Value: CE->getValue());
299 }
300
301 bool isOffsetOfLocal() const override { return isImm() && Imm.LocalRef; }
302
303 bool needAddressOf() const override { return AddressOf; }
304
305 bool isMem() const override { return Kind == Memory; }
306 bool isMemUnsized() const {
307 return Kind == Memory && Mem.Size == 0;
308 }
309 bool isMem8() const {
310 return Kind == Memory && (!Mem.Size || Mem.Size == 8);
311 }
312 bool isMem16() const {
313 return Kind == Memory && (!Mem.Size || Mem.Size == 16);
314 }
315 bool isMem32() const {
316 return Kind == Memory && (!Mem.Size || Mem.Size == 32);
317 }
318 bool isMem64() const {
319 return Kind == Memory && (!Mem.Size || Mem.Size == 64);
320 }
321 bool isMem80() const {
322 return Kind == Memory && (!Mem.Size || Mem.Size == 80);
323 }
324 bool isMem128() const {
325 return Kind == Memory && (!Mem.Size || Mem.Size == 128);
326 }
327 bool isMem256() const {
328 return Kind == Memory && (!Mem.Size || Mem.Size == 256);
329 }
330 bool isMem512() const {
331 return Kind == Memory && (!Mem.Size || Mem.Size == 512);
332 }
333
334 bool isSibMem() const {
335 return isMem() && Mem.BaseReg != X86::RIP && Mem.BaseReg != X86::EIP;
336 }
337
338 bool isMemIndexReg(unsigned LowR, unsigned HighR) const {
339 assert(Kind == Memory && "Invalid access!");
340 return Mem.IndexReg >= LowR && Mem.IndexReg <= HighR;
341 }
342
343 bool isMem64_RC128() const {
344 return isMem64() && isMemIndexReg(LowR: X86::XMM0, HighR: X86::XMM15);
345 }
346 bool isMem128_RC128() const {
347 return isMem128() && isMemIndexReg(LowR: X86::XMM0, HighR: X86::XMM15);
348 }
349 bool isMem128_RC256() const {
350 return isMem128() && isMemIndexReg(LowR: X86::YMM0, HighR: X86::YMM15);
351 }
352 bool isMem256_RC128() const {
353 return isMem256() && isMemIndexReg(LowR: X86::XMM0, HighR: X86::XMM15);
354 }
355 bool isMem256_RC256() const {
356 return isMem256() && isMemIndexReg(LowR: X86::YMM0, HighR: X86::YMM15);
357 }
358
359 bool isMem64_RC128X() const {
360 return isMem64() && X86II::isXMMReg(RegNo: Mem.IndexReg);
361 }
362 bool isMem128_RC128X() const {
363 return isMem128() && X86II::isXMMReg(RegNo: Mem.IndexReg);
364 }
365 bool isMem128_RC256X() const {
366 return isMem128() && X86II::isYMMReg(RegNo: Mem.IndexReg);
367 }
368 bool isMem256_RC128X() const {
369 return isMem256() && X86II::isXMMReg(RegNo: Mem.IndexReg);
370 }
371 bool isMem256_RC256X() const {
372 return isMem256() && X86II::isYMMReg(RegNo: Mem.IndexReg);
373 }
374 bool isMem256_RC512() const {
375 return isMem256() && X86II::isZMMReg(RegNo: Mem.IndexReg);
376 }
377 bool isMem512_RC256X() const {
378 return isMem512() && X86II::isYMMReg(RegNo: Mem.IndexReg);
379 }
380 bool isMem512_RC512() const {
381 return isMem512() && X86II::isZMMReg(RegNo: Mem.IndexReg);
382 }
383 bool isMem512_GR16() const {
384 if (!isMem512())
385 return false;
386 if (getMemBaseReg() &&
387 !X86MCRegisterClasses[X86::GR16RegClassID].contains(Reg: getMemBaseReg()))
388 return false;
389 return true;
390 }
391 bool isMem512_GR32() const {
392 if (!isMem512())
393 return false;
394 if (getMemBaseReg() &&
395 !X86MCRegisterClasses[X86::GR32RegClassID].contains(Reg: getMemBaseReg()) &&
396 getMemBaseReg() != X86::EIP)
397 return false;
398 if (getMemIndexReg() &&
399 !X86MCRegisterClasses[X86::GR32RegClassID].contains(Reg: getMemIndexReg()) &&
400 getMemIndexReg() != X86::EIZ)
401 return false;
402 return true;
403 }
404 bool isMem512_GR64() const {
405 if (!isMem512())
406 return false;
407 if (getMemBaseReg() &&
408 !X86MCRegisterClasses[X86::GR64RegClassID].contains(Reg: getMemBaseReg()) &&
409 getMemBaseReg() != X86::RIP)
410 return false;
411 if (getMemIndexReg() &&
412 !X86MCRegisterClasses[X86::GR64RegClassID].contains(Reg: getMemIndexReg()) &&
413 getMemIndexReg() != X86::RIZ)
414 return false;
415 return true;
416 }
417
418 bool isAbsMem() const {
419 return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
420 !getMemIndexReg() && getMemScale() == 1 && isMaybeDirectBranchDest();
421 }
422
423 bool isAVX512RC() const{
424 return isImm();
425 }
426
427 bool isAbsMem16() const {
428 return isAbsMem() && Mem.ModeSize == 16;
429 }
430
431 bool isMemUseUpRegs() const override { return UseUpRegs; }
432
433 bool isSrcIdx() const {
434 return !getMemIndexReg() && getMemScale() == 1 &&
435 (getMemBaseReg() == X86::RSI || getMemBaseReg() == X86::ESI ||
436 getMemBaseReg() == X86::SI) && isa<MCConstantExpr>(Val: getMemDisp()) &&
437 cast<MCConstantExpr>(Val: getMemDisp())->getValue() == 0;
438 }
439 bool isSrcIdx8() const {
440 return isMem8() && isSrcIdx();
441 }
442 bool isSrcIdx16() const {
443 return isMem16() && isSrcIdx();
444 }
445 bool isSrcIdx32() const {
446 return isMem32() && isSrcIdx();
447 }
448 bool isSrcIdx64() const {
449 return isMem64() && isSrcIdx();
450 }
451
452 bool isDstIdx() const {
453 return !getMemIndexReg() && getMemScale() == 1 &&
454 (getMemSegReg() == 0 || getMemSegReg() == X86::ES) &&
455 (getMemBaseReg() == X86::RDI || getMemBaseReg() == X86::EDI ||
456 getMemBaseReg() == X86::DI) && isa<MCConstantExpr>(Val: getMemDisp()) &&
457 cast<MCConstantExpr>(Val: getMemDisp())->getValue() == 0;
458 }
459 bool isDstIdx8() const {
460 return isMem8() && isDstIdx();
461 }
462 bool isDstIdx16() const {
463 return isMem16() && isDstIdx();
464 }
465 bool isDstIdx32() const {
466 return isMem32() && isDstIdx();
467 }
468 bool isDstIdx64() const {
469 return isMem64() && isDstIdx();
470 }
471
472 bool isMemOffs() const {
473 return Kind == Memory && !getMemBaseReg() && !getMemIndexReg() &&
474 getMemScale() == 1;
475 }
476
477 bool isMemOffs16_8() const {
478 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 8);
479 }
480 bool isMemOffs16_16() const {
481 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 16);
482 }
483 bool isMemOffs16_32() const {
484 return isMemOffs() && Mem.ModeSize == 16 && (!Mem.Size || Mem.Size == 32);
485 }
486 bool isMemOffs32_8() const {
487 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 8);
488 }
489 bool isMemOffs32_16() const {
490 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 16);
491 }
492 bool isMemOffs32_32() const {
493 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 32);
494 }
495 bool isMemOffs32_64() const {
496 return isMemOffs() && Mem.ModeSize == 32 && (!Mem.Size || Mem.Size == 64);
497 }
498 bool isMemOffs64_8() const {
499 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 8);
500 }
501 bool isMemOffs64_16() const {
502 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 16);
503 }
504 bool isMemOffs64_32() const {
505 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 32);
506 }
507 bool isMemOffs64_64() const {
508 return isMemOffs() && Mem.ModeSize == 64 && (!Mem.Size || Mem.Size == 64);
509 }
510
511 bool isPrefix() const { return Kind == Prefix; }
512 bool isReg() const override { return Kind == Register; }
513 bool isDXReg() const { return Kind == DXRegister; }
514
515 bool isGR32orGR64() const {
516 return Kind == Register &&
517 (X86MCRegisterClasses[X86::GR32RegClassID].contains(Reg: getReg()) ||
518 X86MCRegisterClasses[X86::GR64RegClassID].contains(Reg: getReg()));
519 }
520
521 bool isGR16orGR32orGR64() const {
522 return Kind == Register &&
523 (X86MCRegisterClasses[X86::GR16RegClassID].contains(Reg: getReg()) ||
524 X86MCRegisterClasses[X86::GR32RegClassID].contains(Reg: getReg()) ||
525 X86MCRegisterClasses[X86::GR64RegClassID].contains(Reg: getReg()));
526 }
527
528 bool isVectorReg() const {
529 return Kind == Register &&
530 (X86MCRegisterClasses[X86::VR64RegClassID].contains(Reg: getReg()) ||
531 X86MCRegisterClasses[X86::VR128XRegClassID].contains(Reg: getReg()) ||
532 X86MCRegisterClasses[X86::VR256XRegClassID].contains(Reg: getReg()) ||
533 X86MCRegisterClasses[X86::VR512RegClassID].contains(Reg: getReg()));
534 }
535
536 bool isVK1Pair() const {
537 return Kind == Register &&
538 X86MCRegisterClasses[X86::VK1RegClassID].contains(Reg: getReg());
539 }
540
541 bool isVK2Pair() const {
542 return Kind == Register &&
543 X86MCRegisterClasses[X86::VK2RegClassID].contains(Reg: getReg());
544 }
545
546 bool isVK4Pair() const {
547 return Kind == Register &&
548 X86MCRegisterClasses[X86::VK4RegClassID].contains(Reg: getReg());
549 }
550
551 bool isVK8Pair() const {
552 return Kind == Register &&
553 X86MCRegisterClasses[X86::VK8RegClassID].contains(Reg: getReg());
554 }
555
556 bool isVK16Pair() const {
557 return Kind == Register &&
558 X86MCRegisterClasses[X86::VK16RegClassID].contains(Reg: getReg());
559 }
560
561 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
562 // Add as immediates when possible.
563 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: Expr))
564 Inst.addOperand(Op: MCOperand::createImm(Val: CE->getValue()));
565 else
566 Inst.addOperand(Op: MCOperand::createExpr(Val: Expr));
567 }
568
569 void addRegOperands(MCInst &Inst, unsigned N) const {
570 assert(N == 1 && "Invalid number of operands!");
571 Inst.addOperand(Op: MCOperand::createReg(Reg: getReg()));
572 }
573
574 void addGR32orGR64Operands(MCInst &Inst, unsigned N) const {
575 assert(N == 1 && "Invalid number of operands!");
576 MCRegister RegNo = getReg();
577 if (X86MCRegisterClasses[X86::GR64RegClassID].contains(Reg: RegNo))
578 RegNo = getX86SubSuperRegister(Reg: RegNo, Size: 32);
579 Inst.addOperand(Op: MCOperand::createReg(Reg: RegNo));
580 }
581
582 void addGR16orGR32orGR64Operands(MCInst &Inst, unsigned N) const {
583 assert(N == 1 && "Invalid number of operands!");
584 MCRegister RegNo = getReg();
585 if (X86MCRegisterClasses[X86::GR32RegClassID].contains(Reg: RegNo) ||
586 X86MCRegisterClasses[X86::GR64RegClassID].contains(Reg: RegNo))
587 RegNo = getX86SubSuperRegister(Reg: RegNo, Size: 16);
588 Inst.addOperand(Op: MCOperand::createReg(Reg: RegNo));
589 }
590
591 void addAVX512RCOperands(MCInst &Inst, unsigned N) const {
592 assert(N == 1 && "Invalid number of operands!");
593 addExpr(Inst, Expr: getImm());
594 }
595
596 void addImmOperands(MCInst &Inst, unsigned N) const {
597 assert(N == 1 && "Invalid number of operands!");
598 addExpr(Inst, Expr: getImm());
599 }
600
601 void addMaskPairOperands(MCInst &Inst, unsigned N) const {
602 assert(N == 1 && "Invalid number of operands!");
603 unsigned Reg = getReg();
604 switch (Reg) {
605 case X86::K0:
606 case X86::K1:
607 Reg = X86::K0_K1;
608 break;
609 case X86::K2:
610 case X86::K3:
611 Reg = X86::K2_K3;
612 break;
613 case X86::K4:
614 case X86::K5:
615 Reg = X86::K4_K5;
616 break;
617 case X86::K6:
618 case X86::K7:
619 Reg = X86::K6_K7;
620 break;
621 }
622 Inst.addOperand(Op: MCOperand::createReg(Reg));
623 }
624
625 void addMemOperands(MCInst &Inst, unsigned N) const {
626 assert((N == 5) && "Invalid number of operands!");
627 if (getMemBaseReg())
628 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemBaseReg()));
629 else
630 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemDefaultBaseReg()));
631 Inst.addOperand(Op: MCOperand::createImm(Val: getMemScale()));
632 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemIndexReg()));
633 addExpr(Inst, Expr: getMemDisp());
634 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemSegReg()));
635 }
636
637 void addAbsMemOperands(MCInst &Inst, unsigned N) const {
638 assert((N == 1) && "Invalid number of operands!");
639 // Add as immediates when possible.
640 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getMemDisp()))
641 Inst.addOperand(Op: MCOperand::createImm(Val: CE->getValue()));
642 else
643 Inst.addOperand(Op: MCOperand::createExpr(Val: getMemDisp()));
644 }
645
646 void addSrcIdxOperands(MCInst &Inst, unsigned N) const {
647 assert((N == 2) && "Invalid number of operands!");
648 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemBaseReg()));
649 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemSegReg()));
650 }
651
652 void addDstIdxOperands(MCInst &Inst, unsigned N) const {
653 assert((N == 1) && "Invalid number of operands!");
654 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemBaseReg()));
655 }
656
657 void addMemOffsOperands(MCInst &Inst, unsigned N) const {
658 assert((N == 2) && "Invalid number of operands!");
659 // Add as immediates when possible.
660 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Val: getMemDisp()))
661 Inst.addOperand(Op: MCOperand::createImm(Val: CE->getValue()));
662 else
663 Inst.addOperand(Op: MCOperand::createExpr(Val: getMemDisp()));
664 Inst.addOperand(Op: MCOperand::createReg(Reg: getMemSegReg()));
665 }
666
667 static std::unique_ptr<X86Operand> CreateToken(StringRef Str, SMLoc Loc) {
668 SMLoc EndLoc = SMLoc::getFromPointer(Ptr: Loc.getPointer() + Str.size());
669 auto Res = std::make_unique<X86Operand>(args: Token, args&: Loc, args&: EndLoc);
670 Res->Tok.Data = Str.data();
671 Res->Tok.Length = Str.size();
672 return Res;
673 }
674
675 static std::unique_ptr<X86Operand>
676 CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc,
677 bool AddressOf = false, SMLoc OffsetOfLoc = SMLoc(),
678 StringRef SymName = StringRef(), void *OpDecl = nullptr) {
679 auto Res = std::make_unique<X86Operand>(args: Register, args&: StartLoc, args&: EndLoc);
680 Res->Reg.RegNo = RegNo;
681 Res->AddressOf = AddressOf;
682 Res->OffsetOfLoc = OffsetOfLoc;
683 Res->SymName = SymName;
684 Res->OpDecl = OpDecl;
685 return Res;
686 }
687
688 static std::unique_ptr<X86Operand>
689 CreateDXReg(SMLoc StartLoc, SMLoc EndLoc) {
690 return std::make_unique<X86Operand>(args: DXRegister, args&: StartLoc, args&: EndLoc);
691 }
692
693 static std::unique_ptr<X86Operand>
694 CreatePrefix(unsigned Prefixes, SMLoc StartLoc, SMLoc EndLoc) {
695 auto Res = std::make_unique<X86Operand>(args: Prefix, args&: StartLoc, args&: EndLoc);
696 Res->Pref.Prefixes = Prefixes;
697 return Res;
698 }
699
700 static std::unique_ptr<X86Operand> CreateImm(const MCExpr *Val,
701 SMLoc StartLoc, SMLoc EndLoc,
702 StringRef SymName = StringRef(),
703 void *OpDecl = nullptr,
704 bool GlobalRef = true) {
705 auto Res = std::make_unique<X86Operand>(args: Immediate, args&: StartLoc, args&: EndLoc);
706 Res->Imm.Val = Val;
707 Res->Imm.LocalRef = !GlobalRef;
708 Res->SymName = SymName;
709 Res->OpDecl = OpDecl;
710 Res->AddressOf = true;
711 return Res;
712 }
713
714 /// Create an absolute memory operand.
715 static std::unique_ptr<X86Operand>
716 CreateMem(unsigned ModeSize, const MCExpr *Disp, SMLoc StartLoc, SMLoc EndLoc,
717 unsigned Size = 0, StringRef SymName = StringRef(),
718 void *OpDecl = nullptr, unsigned FrontendSize = 0,
719 bool UseUpRegs = false, bool MaybeDirectBranchDest = true) {
720 auto Res = std::make_unique<X86Operand>(args: Memory, args&: StartLoc, args&: EndLoc);
721 Res->Mem.SegReg = 0;
722 Res->Mem.Disp = Disp;
723 Res->Mem.BaseReg = 0;
724 Res->Mem.DefaultBaseReg = 0;
725 Res->Mem.IndexReg = 0;
726 Res->Mem.Scale = 1;
727 Res->Mem.Size = Size;
728 Res->Mem.ModeSize = ModeSize;
729 Res->Mem.FrontendSize = FrontendSize;
730 Res->Mem.MaybeDirectBranchDest = MaybeDirectBranchDest;
731 Res->UseUpRegs = UseUpRegs;
732 Res->SymName = SymName;
733 Res->OpDecl = OpDecl;
734 Res->AddressOf = false;
735 return Res;
736 }
737
738 /// Create a generalized memory operand.
739 static std::unique_ptr<X86Operand>
740 CreateMem(unsigned ModeSize, unsigned SegReg, const MCExpr *Disp,
741 unsigned BaseReg, unsigned IndexReg, unsigned Scale, SMLoc StartLoc,
742 SMLoc EndLoc, unsigned Size = 0,
743 unsigned DefaultBaseReg = X86::NoRegister,
744 StringRef SymName = StringRef(), void *OpDecl = nullptr,
745 unsigned FrontendSize = 0, bool UseUpRegs = false,
746 bool MaybeDirectBranchDest = true) {
747 // We should never just have a displacement, that should be parsed as an
748 // absolute memory operand.
749 assert((SegReg || BaseReg || IndexReg || DefaultBaseReg) &&
750 "Invalid memory operand!");
751
752 // The scale should always be one of {1,2,4,8}.
753 assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
754 "Invalid scale!");
755 auto Res = std::make_unique<X86Operand>(args: Memory, args&: StartLoc, args&: EndLoc);
756 Res->Mem.SegReg = SegReg;
757 Res->Mem.Disp = Disp;
758 Res->Mem.BaseReg = BaseReg;
759 Res->Mem.DefaultBaseReg = DefaultBaseReg;
760 Res->Mem.IndexReg = IndexReg;
761 Res->Mem.Scale = Scale;
762 Res->Mem.Size = Size;
763 Res->Mem.ModeSize = ModeSize;
764 Res->Mem.FrontendSize = FrontendSize;
765 Res->Mem.MaybeDirectBranchDest = MaybeDirectBranchDest;
766 Res->UseUpRegs = UseUpRegs;
767 Res->SymName = SymName;
768 Res->OpDecl = OpDecl;
769 Res->AddressOf = false;
770 return Res;
771 }
772};
773
774} // end namespace llvm
775
776#endif // LLVM_LIB_TARGET_X86_ASMPARSER_X86OPERAND_H
777