xref: /freebsd/contrib/llvm-project/llvm/lib/Target/X86/MCTargetDesc/X86ATTInstPrinter.cpp (revision 700637cbb5e582861067a11aaca4d053546871d2)
1 //===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===//
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 // This file includes code for rendering MCInst instances as AT&T-style
10 // assembly.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "X86ATTInstPrinter.h"
15 #include "X86BaseInfo.h"
16 #include "X86InstComments.h"
17 #include "llvm/ADT/SmallString.h"
18 #include "llvm/MC/MCAsmInfo.h"
19 #include "llvm/MC/MCExpr.h"
20 #include "llvm/MC/MCInst.h"
21 #include "llvm/MC/MCInstrAnalysis.h"
22 #include "llvm/MC/MCInstrInfo.h"
23 #include "llvm/MC/MCSubtargetInfo.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include "llvm/Support/Format.h"
26 #include "llvm/Support/raw_ostream.h"
27 #include <cassert>
28 #include <cinttypes>
29 #include <cstdint>
30 
31 using namespace llvm;
32 
33 #define DEBUG_TYPE "asm-printer"
34 
35 // Include the auto-generated portion of the assembly writer.
36 #define PRINT_ALIAS_INSTR
37 #include "X86GenAsmWriter.inc"
38 
39 // Print an MCExpr as an operand. Similar to GCC, wrap the output in parentheses
40 // if it begins with '$', as '$' in an operand position indicates an immediate
41 // value in the AT&T syntax.
printExprOperand(raw_ostream & OS,const MCExpr & E)42 void X86ATTInstPrinter::printExprOperand(raw_ostream &OS, const MCExpr &E) {
43   SmallString<128> S;
44   {
45     raw_svector_ostream SOS(S);
46     MAI.printExpr(SOS, E);
47   }
48   if (S.starts_with("$"))
49     OS << '(' << S << ')';
50   else
51     OS << S;
52 }
53 
printRegName(raw_ostream & OS,MCRegister Reg)54 void X86ATTInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) {
55   markup(OS, Markup::Register) << '%' << getRegisterName(Reg);
56 }
57 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & OS)58 void X86ATTInstPrinter::printInst(const MCInst *MI, uint64_t Address,
59                                   StringRef Annot, const MCSubtargetInfo &STI,
60                                   raw_ostream &OS) {
61   // If verbose assembly is enabled, we can print some informative comments.
62   if (CommentStream)
63     HasCustomInstComment = EmitAnyX86InstComments(MI, *CommentStream, MII);
64 
65   printInstFlags(MI, OS, STI);
66 
67   // Output CALLpcrel32 as "callq" in 64-bit mode.
68   // In Intel annotation it's always emitted as "call".
69   //
70   // TODO: Probably this hack should be redesigned via InstAlias in
71   // InstrInfo.td as soon as Requires clause is supported properly
72   // for InstAlias.
73   if (MI->getOpcode() == X86::CALLpcrel32 &&
74       (STI.hasFeature(X86::Is64Bit))) {
75     OS << "\tcallq\t";
76     printPCRelImm(MI, Address, 0, OS);
77   }
78   // data16 and data32 both have the same encoding of 0x66. While data32 is
79   // valid only in 16 bit systems, data16 is valid in the rest.
80   // There seems to be some lack of support of the Requires clause that causes
81   // 0x66 to be interpreted as "data16" by the asm printer.
82   // Thus we add an adjustment here in order to print the "right" instruction.
83   else if (MI->getOpcode() == X86::DATA16_PREFIX &&
84            STI.hasFeature(X86::Is16Bit)) {
85     OS << "\tdata32";
86   }
87   // Try to print any aliases first.
88   else if (!printAliasInstr(MI, Address, OS) && !printVecCompareInstr(MI, OS))
89     printInstruction(MI, Address, OS);
90 
91   // Next always print the annotation.
92   printAnnotation(OS, Annot);
93 }
94 
printVecCompareInstr(const MCInst * MI,raw_ostream & OS)95 bool X86ATTInstPrinter::printVecCompareInstr(const MCInst *MI,
96                                              raw_ostream &OS) {
97   if (MI->getNumOperands() == 0 ||
98       !MI->getOperand(MI->getNumOperands() - 1).isImm())
99     return false;
100 
101   int64_t Imm = MI->getOperand(MI->getNumOperands() - 1).getImm();
102 
103   const MCInstrDesc &Desc = MII.get(MI->getOpcode());
104 
105   // Custom print the vector compare instructions to get the immediate
106   // translated into the mnemonic.
107   switch (MI->getOpcode()) {
108   case X86::CMPPDrmi:     case X86::CMPPDrri:
109   case X86::CMPPSrmi:     case X86::CMPPSrri:
110   case X86::CMPSDrmi:     case X86::CMPSDrri:
111   case X86::CMPSDrmi_Int: case X86::CMPSDrri_Int:
112   case X86::CMPSSrmi:     case X86::CMPSSrri:
113   case X86::CMPSSrmi_Int: case X86::CMPSSrri_Int:
114     if (Imm >= 0 && Imm <= 7) {
115       OS << '\t';
116       printCMPMnemonic(MI, /*IsVCMP*/false, OS);
117 
118       if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {
119         if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS)
120           printdwordmem(MI, 2, OS);
121         else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD)
122           printqwordmem(MI, 2, OS);
123         else
124           printxmmwordmem(MI, 2, OS);
125       } else
126         printOperand(MI, 2, OS);
127 
128       // Skip operand 1 as its tied to the dest.
129 
130       OS << ", ";
131       printOperand(MI, 0, OS);
132       return true;
133     }
134     break;
135 
136   case X86::VCMPPDrmi:       case X86::VCMPPDrri:
137   case X86::VCMPPDYrmi:      case X86::VCMPPDYrri:
138   case X86::VCMPPDZ128rmi:   case X86::VCMPPDZ128rri:
139   case X86::VCMPPDZ256rmi:   case X86::VCMPPDZ256rri:
140   case X86::VCMPPDZrmi:      case X86::VCMPPDZrri:
141   case X86::VCMPPSrmi:       case X86::VCMPPSrri:
142   case X86::VCMPPSYrmi:      case X86::VCMPPSYrri:
143   case X86::VCMPPSZ128rmi:   case X86::VCMPPSZ128rri:
144   case X86::VCMPPSZ256rmi:   case X86::VCMPPSZ256rri:
145   case X86::VCMPPSZrmi:      case X86::VCMPPSZrri:
146   case X86::VCMPSDrmi:       case X86::VCMPSDrri:
147   case X86::VCMPSDZrmi:      case X86::VCMPSDZrri:
148   case X86::VCMPSDrmi_Int:   case X86::VCMPSDrri_Int:
149   case X86::VCMPSDZrmi_Int:  case X86::VCMPSDZrri_Int:
150   case X86::VCMPSSrmi:       case X86::VCMPSSrri:
151   case X86::VCMPSSZrmi:      case X86::VCMPSSZrri:
152   case X86::VCMPSSrmi_Int:   case X86::VCMPSSrri_Int:
153   case X86::VCMPSSZrmi_Int:  case X86::VCMPSSZrri_Int:
154   case X86::VCMPPDZ128rmik:  case X86::VCMPPDZ128rrik:
155   case X86::VCMPPDZ256rmik:  case X86::VCMPPDZ256rrik:
156   case X86::VCMPPDZrmik:     case X86::VCMPPDZrrik:
157   case X86::VCMPPSZ128rmik:  case X86::VCMPPSZ128rrik:
158   case X86::VCMPPSZ256rmik:  case X86::VCMPPSZ256rrik:
159   case X86::VCMPPSZrmik:     case X86::VCMPPSZrrik:
160   case X86::VCMPSDZrmik_Int: case X86::VCMPSDZrrik_Int:
161   case X86::VCMPSSZrmik_Int: case X86::VCMPSSZrrik_Int:
162   case X86::VCMPPDZ128rmbi:  case X86::VCMPPDZ128rmbik:
163   case X86::VCMPPDZ256rmbi:  case X86::VCMPPDZ256rmbik:
164   case X86::VCMPPDZrmbi:     case X86::VCMPPDZrmbik:
165   case X86::VCMPPSZ128rmbi:  case X86::VCMPPSZ128rmbik:
166   case X86::VCMPPSZ256rmbi:  case X86::VCMPPSZ256rmbik:
167   case X86::VCMPPSZrmbi:     case X86::VCMPPSZrmbik:
168   case X86::VCMPPDZrrib:     case X86::VCMPPDZrribk:
169   case X86::VCMPPSZrrib:     case X86::VCMPPSZrribk:
170   case X86::VCMPSDZrrib_Int: case X86::VCMPSDZrribk_Int:
171   case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrribk_Int:
172   case X86::VCMPPHZ128rmi:   case X86::VCMPPHZ128rri:
173   case X86::VCMPPHZ256rmi:   case X86::VCMPPHZ256rri:
174   case X86::VCMPPHZrmi:      case X86::VCMPPHZrri:
175   case X86::VCMPSHZrmi:      case X86::VCMPSHZrri:
176   case X86::VCMPSHZrmi_Int:  case X86::VCMPSHZrri_Int:
177   case X86::VCMPPHZ128rmik:  case X86::VCMPPHZ128rrik:
178   case X86::VCMPPHZ256rmik:  case X86::VCMPPHZ256rrik:
179   case X86::VCMPPHZrmik:     case X86::VCMPPHZrrik:
180   case X86::VCMPSHZrmik_Int: case X86::VCMPSHZrrik_Int:
181   case X86::VCMPPHZ128rmbi:  case X86::VCMPPHZ128rmbik:
182   case X86::VCMPPHZ256rmbi:  case X86::VCMPPHZ256rmbik:
183   case X86::VCMPPHZrmbi:     case X86::VCMPPHZrmbik:
184   case X86::VCMPPHZrrib:     case X86::VCMPPHZrribk:
185   case X86::VCMPSHZrrib_Int: case X86::VCMPSHZrribk_Int:
186   case X86::VCMPBF16Z128rmi:  case X86::VCMPBF16Z128rri:
187   case X86::VCMPBF16Z256rmi:  case X86::VCMPBF16Z256rri:
188   case X86::VCMPBF16Zrmi:     case X86::VCMPBF16Zrri:
189   case X86::VCMPBF16Z128rmik: case X86::VCMPBF16Z128rrik:
190   case X86::VCMPBF16Z256rmik: case X86::VCMPBF16Z256rrik:
191   case X86::VCMPBF16Zrmik:    case X86::VCMPBF16Zrrik:
192   case X86::VCMPBF16Z128rmbi: case X86::VCMPBF16Z128rmbik:
193   case X86::VCMPBF16Z256rmbi: case X86::VCMPBF16Z256rmbik:
194   case X86::VCMPBF16Zrmbi:    case X86::VCMPBF16Zrmbik:
195     if (Imm >= 0 && Imm <= 31) {
196       OS << '\t';
197       printCMPMnemonic(MI, /*IsVCMP*/true, OS);
198 
199       unsigned CurOp = (Desc.TSFlags & X86II::EVEX_K) ? 3 : 2;
200 
201       if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {
202         if (Desc.TSFlags & X86II::EVEX_B) {
203           // Broadcast form.
204           // Load size is word for TA map. Otherwise it is based on W-bit.
205           if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) {
206             assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!");
207             printwordmem(MI, CurOp--, OS);
208           } else if (Desc.TSFlags & X86II::REX_W) {
209             printqwordmem(MI, CurOp--, OS);
210           } else {
211             printdwordmem(MI, CurOp--, OS);
212           }
213 
214           // Print the number of elements broadcasted.
215           unsigned NumElts;
216           if (Desc.TSFlags & X86II::EVEX_L2)
217             NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16;
218           else if (Desc.TSFlags & X86II::VEX_L)
219             NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8;
220           else
221             NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4;
222           if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) {
223             assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!");
224             NumElts *= 2;
225           }
226           OS << "{1to" << NumElts << "}";
227         } else {
228           if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) {
229             if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA)
230               printwordmem(MI, CurOp--, OS);
231             else
232               printdwordmem(MI, CurOp--, OS);
233           } else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD &&
234                      (Desc.TSFlags & X86II::OpMapMask) != X86II::TA) {
235             printqwordmem(MI, CurOp--, OS);
236           } else if (Desc.TSFlags & X86II::EVEX_L2) {
237             printzmmwordmem(MI, CurOp--, OS);
238           } else if (Desc.TSFlags & X86II::VEX_L) {
239             printymmwordmem(MI, CurOp--, OS);
240           } else {
241             printxmmwordmem(MI, CurOp--, OS);
242           }
243         }
244       } else {
245         if (Desc.TSFlags & X86II::EVEX_B)
246           OS << "{sae}, ";
247         printOperand(MI, CurOp--, OS);
248       }
249 
250       OS << ", ";
251       printOperand(MI, CurOp--, OS);
252       OS << ", ";
253       printOperand(MI, 0, OS);
254       if (CurOp > 0) {
255         // Print mask operand.
256         OS << " {";
257         printOperand(MI, CurOp--, OS);
258         OS << "}";
259       }
260 
261       return true;
262     }
263     break;
264 
265   case X86::VPCOMBmi:  case X86::VPCOMBri:
266   case X86::VPCOMDmi:  case X86::VPCOMDri:
267   case X86::VPCOMQmi:  case X86::VPCOMQri:
268   case X86::VPCOMUBmi: case X86::VPCOMUBri:
269   case X86::VPCOMUDmi: case X86::VPCOMUDri:
270   case X86::VPCOMUQmi: case X86::VPCOMUQri:
271   case X86::VPCOMUWmi: case X86::VPCOMUWri:
272   case X86::VPCOMWmi:  case X86::VPCOMWri:
273     if (Imm >= 0 && Imm <= 7) {
274       OS << '\t';
275       printVPCOMMnemonic(MI, OS);
276 
277       if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem)
278         printxmmwordmem(MI, 2, OS);
279       else
280         printOperand(MI, 2, OS);
281 
282       OS << ", ";
283       printOperand(MI, 1, OS);
284       OS << ", ";
285       printOperand(MI, 0, OS);
286       return true;
287     }
288     break;
289 
290   case X86::VPCMPBZ128rmi:   case X86::VPCMPBZ128rri:
291   case X86::VPCMPBZ256rmi:   case X86::VPCMPBZ256rri:
292   case X86::VPCMPBZrmi:      case X86::VPCMPBZrri:
293   case X86::VPCMPDZ128rmi:   case X86::VPCMPDZ128rri:
294   case X86::VPCMPDZ256rmi:   case X86::VPCMPDZ256rri:
295   case X86::VPCMPDZrmi:      case X86::VPCMPDZrri:
296   case X86::VPCMPQZ128rmi:   case X86::VPCMPQZ128rri:
297   case X86::VPCMPQZ256rmi:   case X86::VPCMPQZ256rri:
298   case X86::VPCMPQZrmi:      case X86::VPCMPQZrri:
299   case X86::VPCMPUBZ128rmi:  case X86::VPCMPUBZ128rri:
300   case X86::VPCMPUBZ256rmi:  case X86::VPCMPUBZ256rri:
301   case X86::VPCMPUBZrmi:     case X86::VPCMPUBZrri:
302   case X86::VPCMPUDZ128rmi:  case X86::VPCMPUDZ128rri:
303   case X86::VPCMPUDZ256rmi:  case X86::VPCMPUDZ256rri:
304   case X86::VPCMPUDZrmi:     case X86::VPCMPUDZrri:
305   case X86::VPCMPUQZ128rmi:  case X86::VPCMPUQZ128rri:
306   case X86::VPCMPUQZ256rmi:  case X86::VPCMPUQZ256rri:
307   case X86::VPCMPUQZrmi:     case X86::VPCMPUQZrri:
308   case X86::VPCMPUWZ128rmi:  case X86::VPCMPUWZ128rri:
309   case X86::VPCMPUWZ256rmi:  case X86::VPCMPUWZ256rri:
310   case X86::VPCMPUWZrmi:     case X86::VPCMPUWZrri:
311   case X86::VPCMPWZ128rmi:   case X86::VPCMPWZ128rri:
312   case X86::VPCMPWZ256rmi:   case X86::VPCMPWZ256rri:
313   case X86::VPCMPWZrmi:      case X86::VPCMPWZrri:
314   case X86::VPCMPBZ128rmik:  case X86::VPCMPBZ128rrik:
315   case X86::VPCMPBZ256rmik:  case X86::VPCMPBZ256rrik:
316   case X86::VPCMPBZrmik:     case X86::VPCMPBZrrik:
317   case X86::VPCMPDZ128rmik:  case X86::VPCMPDZ128rrik:
318   case X86::VPCMPDZ256rmik:  case X86::VPCMPDZ256rrik:
319   case X86::VPCMPDZrmik:     case X86::VPCMPDZrrik:
320   case X86::VPCMPQZ128rmik:  case X86::VPCMPQZ128rrik:
321   case X86::VPCMPQZ256rmik:  case X86::VPCMPQZ256rrik:
322   case X86::VPCMPQZrmik:     case X86::VPCMPQZrrik:
323   case X86::VPCMPUBZ128rmik: case X86::VPCMPUBZ128rrik:
324   case X86::VPCMPUBZ256rmik: case X86::VPCMPUBZ256rrik:
325   case X86::VPCMPUBZrmik:    case X86::VPCMPUBZrrik:
326   case X86::VPCMPUDZ128rmik: case X86::VPCMPUDZ128rrik:
327   case X86::VPCMPUDZ256rmik: case X86::VPCMPUDZ256rrik:
328   case X86::VPCMPUDZrmik:    case X86::VPCMPUDZrrik:
329   case X86::VPCMPUQZ128rmik: case X86::VPCMPUQZ128rrik:
330   case X86::VPCMPUQZ256rmik: case X86::VPCMPUQZ256rrik:
331   case X86::VPCMPUQZrmik:    case X86::VPCMPUQZrrik:
332   case X86::VPCMPUWZ128rmik: case X86::VPCMPUWZ128rrik:
333   case X86::VPCMPUWZ256rmik: case X86::VPCMPUWZ256rrik:
334   case X86::VPCMPUWZrmik:    case X86::VPCMPUWZrrik:
335   case X86::VPCMPWZ128rmik:  case X86::VPCMPWZ128rrik:
336   case X86::VPCMPWZ256rmik:  case X86::VPCMPWZ256rrik:
337   case X86::VPCMPWZrmik:     case X86::VPCMPWZrrik:
338   case X86::VPCMPDZ128rmbi:  case X86::VPCMPDZ128rmbik:
339   case X86::VPCMPDZ256rmbi:  case X86::VPCMPDZ256rmbik:
340   case X86::VPCMPDZrmbi:     case X86::VPCMPDZrmbik:
341   case X86::VPCMPQZ128rmbi:  case X86::VPCMPQZ128rmbik:
342   case X86::VPCMPQZ256rmbi:  case X86::VPCMPQZ256rmbik:
343   case X86::VPCMPQZrmbi:     case X86::VPCMPQZrmbik:
344   case X86::VPCMPUDZ128rmbi: case X86::VPCMPUDZ128rmbik:
345   case X86::VPCMPUDZ256rmbi: case X86::VPCMPUDZ256rmbik:
346   case X86::VPCMPUDZrmbi:    case X86::VPCMPUDZrmbik:
347   case X86::VPCMPUQZ128rmbi: case X86::VPCMPUQZ128rmbik:
348   case X86::VPCMPUQZ256rmbi: case X86::VPCMPUQZ256rmbik:
349   case X86::VPCMPUQZrmbi:    case X86::VPCMPUQZrmbik:
350     if ((Imm >= 0 && Imm <= 2) || (Imm >= 4 && Imm <= 6)) {
351       OS << '\t';
352       printVPCMPMnemonic(MI, OS);
353 
354       unsigned CurOp = (Desc.TSFlags & X86II::EVEX_K) ? 3 : 2;
355 
356       if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {
357         if (Desc.TSFlags & X86II::EVEX_B) {
358           // Broadcast form.
359           // Load size is based on W-bit as only D and Q are supported.
360           if (Desc.TSFlags & X86II::REX_W)
361             printqwordmem(MI, CurOp--, OS);
362           else
363             printdwordmem(MI, CurOp--, OS);
364 
365           // Print the number of elements broadcasted.
366           unsigned NumElts;
367           if (Desc.TSFlags & X86II::EVEX_L2)
368             NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16;
369           else if (Desc.TSFlags & X86II::VEX_L)
370             NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8;
371           else
372             NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4;
373           OS << "{1to" << NumElts << "}";
374         } else {
375           if (Desc.TSFlags & X86II::EVEX_L2)
376             printzmmwordmem(MI, CurOp--, OS);
377           else if (Desc.TSFlags & X86II::VEX_L)
378             printymmwordmem(MI, CurOp--, OS);
379           else
380             printxmmwordmem(MI, CurOp--, OS);
381         }
382       } else {
383         printOperand(MI, CurOp--, OS);
384       }
385 
386       OS << ", ";
387       printOperand(MI, CurOp--, OS);
388       OS << ", ";
389       printOperand(MI, 0, OS);
390       if (CurOp > 0) {
391         // Print mask operand.
392         OS << " {";
393         printOperand(MI, CurOp--, OS);
394         OS << "}";
395       }
396 
397       return true;
398     }
399     break;
400   }
401 
402   return false;
403 }
404 
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)405 void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
406                                      raw_ostream &O) {
407   const MCOperand &Op = MI->getOperand(OpNo);
408   if (Op.isReg()) {
409     printRegName(O, Op.getReg());
410   } else if (Op.isImm()) {
411     // Print immediates as signed values.
412     int64_t Imm = Op.getImm();
413     markup(O, Markup::Immediate) << '$' << formatImm(Imm);
414 
415     // TODO: This should be in a helper function in the base class, so it can
416     // be used by other printers.
417 
418     // If there are no instruction-specific comments, add a comment clarifying
419     // the hex value of the immediate operand when it isn't in the range
420     // [-256,255].
421     if (CommentStream && !HasCustomInstComment && (Imm > 255 || Imm < -256)) {
422       // Don't print unnecessary hex sign bits.
423       if (Imm == (int16_t)(Imm))
424         *CommentStream << format("imm = 0x%" PRIX16 "\n", (uint16_t)Imm);
425       else if (Imm == (int32_t)(Imm))
426         *CommentStream << format("imm = 0x%" PRIX32 "\n", (uint32_t)Imm);
427       else
428         *CommentStream << format("imm = 0x%" PRIX64 "\n", (uint64_t)Imm);
429     }
430   } else {
431     assert(Op.isExpr() && "unknown operand kind in printOperand");
432     WithMarkup M = markup(O, Markup::Immediate);
433     O << '$';
434     MAI.printExpr(O, *Op.getExpr());
435   }
436 }
437 
printMemReference(const MCInst * MI,unsigned Op,raw_ostream & O)438 void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op,
439                                           raw_ostream &O) {
440   // Do not print the exact form of the memory operand if it references a known
441   // binary object.
442   if (SymbolizeOperands && MIA) {
443     uint64_t Target;
444     if (MIA->evaluateBranch(*MI, 0, 0, Target))
445       return;
446     if (MIA->evaluateMemoryOperandAddress(*MI, /*STI=*/nullptr, 0, 0))
447       return;
448   }
449 
450   const MCOperand &BaseReg = MI->getOperand(Op + X86::AddrBaseReg);
451   const MCOperand &IndexReg = MI->getOperand(Op + X86::AddrIndexReg);
452   const MCOperand &DispSpec = MI->getOperand(Op + X86::AddrDisp);
453 
454   WithMarkup M = markup(O, Markup::Memory);
455 
456   // If this has a segment register, print it.
457   printOptionalSegReg(MI, Op + X86::AddrSegmentReg, O);
458 
459   if (DispSpec.isImm()) {
460     int64_t DispVal = DispSpec.getImm();
461     if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
462       O << formatImm(DispVal);
463   } else {
464     assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
465     printExprOperand(O, *DispSpec.getExpr());
466   }
467 
468   if (IndexReg.getReg() || BaseReg.getReg()) {
469     O << '(';
470     if (BaseReg.getReg())
471       printOperand(MI, Op + X86::AddrBaseReg, O);
472 
473     if (IndexReg.getReg()) {
474       O << ',';
475       printOperand(MI, Op + X86::AddrIndexReg, O);
476       unsigned ScaleVal = MI->getOperand(Op + X86::AddrScaleAmt).getImm();
477       if (ScaleVal != 1) {
478         O << ',';
479         markup(O, Markup::Immediate) << ScaleVal; // never printed in hex.
480       }
481     }
482     O << ')';
483   }
484 }
485 
printSrcIdx(const MCInst * MI,unsigned Op,raw_ostream & O)486 void X86ATTInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,
487                                     raw_ostream &O) {
488   WithMarkup M = markup(O, Markup::Memory);
489 
490   // If this has a segment register, print it.
491   printOptionalSegReg(MI, Op + 1, O);
492 
493   O << "(";
494   printOperand(MI, Op, O);
495   O << ")";
496 }
497 
printDstIdx(const MCInst * MI,unsigned Op,raw_ostream & O)498 void X86ATTInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,
499                                     raw_ostream &O) {
500   WithMarkup M = markup(O, Markup::Memory);
501 
502   O << "%es:(";
503   printOperand(MI, Op, O);
504   O << ")";
505 }
506 
printMemOffset(const MCInst * MI,unsigned Op,raw_ostream & O)507 void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
508                                        raw_ostream &O) {
509   const MCOperand &DispSpec = MI->getOperand(Op);
510 
511   WithMarkup M = markup(O, Markup::Memory);
512 
513   // If this has a segment register, print it.
514   printOptionalSegReg(MI, Op + 1, O);
515 
516   if (DispSpec.isImm()) {
517     O << formatImm(DispSpec.getImm());
518   } else {
519     assert(DispSpec.isExpr() && "non-immediate displacement?");
520     printExprOperand(O, *DispSpec.getExpr());
521   }
522 }
523 
printU8Imm(const MCInst * MI,unsigned Op,raw_ostream & O)524 void X86ATTInstPrinter::printU8Imm(const MCInst *MI, unsigned Op,
525                                    raw_ostream &O) {
526   if (MI->getOperand(Op).isExpr())
527     return printOperand(MI, Op, O);
528 
529   markup(O, Markup::Immediate)
530       << '$' << formatImm(MI->getOperand(Op).getImm() & 0xff);
531 }
532 
printSTiRegOperand(const MCInst * MI,unsigned OpNo,raw_ostream & OS)533 void X86ATTInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo,
534                                            raw_ostream &OS) {
535   MCRegister Reg = MI->getOperand(OpNo).getReg();
536   // Override the default printing to print st(0) instead st.
537   if (Reg == X86::ST0)
538     markup(OS, Markup::Register) << "%st(0)";
539   else
540     printRegName(OS, Reg);
541 }
542