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 | |
27 | namespace llvm { |
28 | |
29 | /// X86Operand - Instances of this class represent a parsed X86 machine |
30 | /// instruction. |
31 | struct 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 | |