1 //===-- X86IntelInstPrinter.cpp - Intel 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 Intel-style
10 // assembly.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #include "X86IntelInstPrinter.h"
15 #include "X86BaseInfo.h"
16 #include "X86InstComments.h"
17 #include "llvm/MC/MCExpr.h"
18 #include "llvm/MC/MCInst.h"
19 #include "llvm/MC/MCInstrAnalysis.h"
20 #include "llvm/MC/MCInstrDesc.h"
21 #include "llvm/MC/MCInstrInfo.h"
22 #include "llvm/MC/MCSubtargetInfo.h"
23 #include "llvm/Support/Casting.h"
24 #include "llvm/Support/ErrorHandling.h"
25 #include <cassert>
26 #include <cstdint>
27 
28 using namespace llvm;
29 
30 #define DEBUG_TYPE "asm-printer"
31 
32 // Include the auto-generated portion of the assembly writer.
33 #define PRINT_ALIAS_INSTR
34 #include "X86GenAsmWriter1.inc"
35 
printRegName(raw_ostream & OS,unsigned RegNo) const36 void X86IntelInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
37   OS << getRegisterName(RegNo);
38 }
39 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & OS)40 void X86IntelInstPrinter::printInst(const MCInst *MI, uint64_t Address,
41                                     StringRef Annot, const MCSubtargetInfo &STI,
42                                     raw_ostream &OS) {
43   printInstFlags(MI, OS);
44 
45   // In 16-bit mode, print data16 as data32.
46   if (MI->getOpcode() == X86::DATA16_PREFIX &&
47       STI.getFeatureBits()[X86::Mode16Bit]) {
48     OS << "\tdata32";
49   } else if (!printAliasInstr(MI, Address, OS) && !printVecCompareInstr(MI, OS))
50     printInstruction(MI, Address, OS);
51 
52   // Next always print the annotation.
53   printAnnotation(OS, Annot);
54 
55   // If verbose assembly is enabled, we can print some informative comments.
56   if (CommentStream)
57     EmitAnyX86InstComments(MI, *CommentStream, MII);
58 }
59 
printVecCompareInstr(const MCInst * MI,raw_ostream & OS)60 bool X86IntelInstPrinter::printVecCompareInstr(const MCInst *MI, raw_ostream &OS) {
61   if (MI->getNumOperands() == 0 ||
62       !MI->getOperand(MI->getNumOperands() - 1).isImm())
63     return false;
64 
65   int64_t Imm = MI->getOperand(MI->getNumOperands() - 1).getImm();
66 
67   const MCInstrDesc &Desc = MII.get(MI->getOpcode());
68 
69   // Custom print the vector compare instructions to get the immediate
70   // translated into the mnemonic.
71   switch (MI->getOpcode()) {
72   case X86::CMPPDrmi:    case X86::CMPPDrri:
73   case X86::CMPPSrmi:    case X86::CMPPSrri:
74   case X86::CMPSDrm:     case X86::CMPSDrr:
75   case X86::CMPSDrm_Int: case X86::CMPSDrr_Int:
76   case X86::CMPSSrm:     case X86::CMPSSrr:
77   case X86::CMPSSrm_Int: case X86::CMPSSrr_Int:
78     if (Imm >= 0 && Imm <= 7) {
79       OS << '\t';
80       printCMPMnemonic(MI, /*IsVCMP*/false, OS);
81       printOperand(MI, 0, OS);
82       OS << ", ";
83       // Skip operand 1 as its tied to the dest.
84 
85       if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {
86         if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS)
87           printdwordmem(MI, 2, OS);
88         else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD)
89           printqwordmem(MI, 2, OS);
90         else
91           printxmmwordmem(MI, 2, OS);
92       } else
93         printOperand(MI, 2, OS);
94 
95       return true;
96     }
97     break;
98 
99   case X86::VCMPPDrmi:      case X86::VCMPPDrri:
100   case X86::VCMPPDYrmi:     case X86::VCMPPDYrri:
101   case X86::VCMPPDZ128rmi:  case X86::VCMPPDZ128rri:
102   case X86::VCMPPDZ256rmi:  case X86::VCMPPDZ256rri:
103   case X86::VCMPPDZrmi:     case X86::VCMPPDZrri:
104   case X86::VCMPPSrmi:      case X86::VCMPPSrri:
105   case X86::VCMPPSYrmi:     case X86::VCMPPSYrri:
106   case X86::VCMPPSZ128rmi:  case X86::VCMPPSZ128rri:
107   case X86::VCMPPSZ256rmi:  case X86::VCMPPSZ256rri:
108   case X86::VCMPPSZrmi:     case X86::VCMPPSZrri:
109   case X86::VCMPSDrm:       case X86::VCMPSDrr:
110   case X86::VCMPSDZrm:      case X86::VCMPSDZrr:
111   case X86::VCMPSDrm_Int:   case X86::VCMPSDrr_Int:
112   case X86::VCMPSDZrm_Int:  case X86::VCMPSDZrr_Int:
113   case X86::VCMPSSrm:       case X86::VCMPSSrr:
114   case X86::VCMPSSZrm:      case X86::VCMPSSZrr:
115   case X86::VCMPSSrm_Int:   case X86::VCMPSSrr_Int:
116   case X86::VCMPSSZrm_Int:  case X86::VCMPSSZrr_Int:
117   case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik:
118   case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik:
119   case X86::VCMPPDZrmik:    case X86::VCMPPDZrrik:
120   case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik:
121   case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik:
122   case X86::VCMPPSZrmik:    case X86::VCMPPSZrrik:
123   case X86::VCMPSDZrm_Intk: case X86::VCMPSDZrr_Intk:
124   case X86::VCMPSSZrm_Intk: case X86::VCMPSSZrr_Intk:
125   case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik:
126   case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik:
127   case X86::VCMPPDZrmbi:    case X86::VCMPPDZrmbik:
128   case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik:
129   case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik:
130   case X86::VCMPPSZrmbi:    case X86::VCMPPSZrmbik:
131   case X86::VCMPPDZrrib:    case X86::VCMPPDZrribk:
132   case X86::VCMPPSZrrib:    case X86::VCMPPSZrribk:
133   case X86::VCMPSDZrrb_Int: case X86::VCMPSDZrrb_Intk:
134   case X86::VCMPSSZrrb_Int: case X86::VCMPSSZrrb_Intk:
135     if (Imm >= 0 && Imm <= 31) {
136       OS << '\t';
137       printCMPMnemonic(MI, /*IsVCMP*/true, OS);
138 
139       unsigned CurOp = 0;
140       printOperand(MI, CurOp++, OS);
141 
142       if (Desc.TSFlags & X86II::EVEX_K) {
143         // Print mask operand.
144         OS << " {";
145         printOperand(MI, CurOp++, OS);
146         OS << "}";
147       }
148       OS << ", ";
149       printOperand(MI, CurOp++, OS);
150       OS << ", ";
151 
152       if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {
153         if (Desc.TSFlags & X86II::EVEX_B) {
154           // Broadcast form.
155           // Load size is based on W-bit.
156           if (Desc.TSFlags & X86II::VEX_W)
157             printqwordmem(MI, CurOp++, OS);
158           else
159             printdwordmem(MI, CurOp++, OS);
160 
161           // Print the number of elements broadcasted.
162           unsigned NumElts;
163           if (Desc.TSFlags & X86II::EVEX_L2)
164             NumElts = (Desc.TSFlags & X86II::VEX_W) ? 8 : 16;
165           else if (Desc.TSFlags & X86II::VEX_L)
166             NumElts = (Desc.TSFlags & X86II::VEX_W) ? 4 : 8;
167           else
168             NumElts = (Desc.TSFlags & X86II::VEX_W) ? 2 : 4;
169           OS << "{1to" << NumElts << "}";
170         } else {
171           if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS)
172             printdwordmem(MI, CurOp++, OS);
173           else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD)
174             printqwordmem(MI, CurOp++, OS);
175           else if (Desc.TSFlags & X86II::EVEX_L2)
176             printzmmwordmem(MI, CurOp++, OS);
177           else if (Desc.TSFlags & X86II::VEX_L)
178             printymmwordmem(MI, CurOp++, OS);
179           else
180             printxmmwordmem(MI, CurOp++, OS);
181         }
182       } else {
183         printOperand(MI, CurOp++, OS);
184         if (Desc.TSFlags & X86II::EVEX_B)
185           OS << ", {sae}";
186       }
187 
188       return true;
189     }
190     break;
191 
192   case X86::VPCOMBmi:  case X86::VPCOMBri:
193   case X86::VPCOMDmi:  case X86::VPCOMDri:
194   case X86::VPCOMQmi:  case X86::VPCOMQri:
195   case X86::VPCOMUBmi: case X86::VPCOMUBri:
196   case X86::VPCOMUDmi: case X86::VPCOMUDri:
197   case X86::VPCOMUQmi: case X86::VPCOMUQri:
198   case X86::VPCOMUWmi: case X86::VPCOMUWri:
199   case X86::VPCOMWmi:  case X86::VPCOMWri:
200     if (Imm >= 0 && Imm <= 7) {
201       OS << '\t';
202       printVPCOMMnemonic(MI, OS);
203       printOperand(MI, 0, OS);
204       OS << ", ";
205       printOperand(MI, 1, OS);
206       OS << ", ";
207       if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem)
208         printxmmwordmem(MI, 2, OS);
209       else
210         printOperand(MI, 2, OS);
211       return true;
212     }
213     break;
214 
215   case X86::VPCMPBZ128rmi:   case X86::VPCMPBZ128rri:
216   case X86::VPCMPBZ256rmi:   case X86::VPCMPBZ256rri:
217   case X86::VPCMPBZrmi:      case X86::VPCMPBZrri:
218   case X86::VPCMPDZ128rmi:   case X86::VPCMPDZ128rri:
219   case X86::VPCMPDZ256rmi:   case X86::VPCMPDZ256rri:
220   case X86::VPCMPDZrmi:      case X86::VPCMPDZrri:
221   case X86::VPCMPQZ128rmi:   case X86::VPCMPQZ128rri:
222   case X86::VPCMPQZ256rmi:   case X86::VPCMPQZ256rri:
223   case X86::VPCMPQZrmi:      case X86::VPCMPQZrri:
224   case X86::VPCMPUBZ128rmi:  case X86::VPCMPUBZ128rri:
225   case X86::VPCMPUBZ256rmi:  case X86::VPCMPUBZ256rri:
226   case X86::VPCMPUBZrmi:     case X86::VPCMPUBZrri:
227   case X86::VPCMPUDZ128rmi:  case X86::VPCMPUDZ128rri:
228   case X86::VPCMPUDZ256rmi:  case X86::VPCMPUDZ256rri:
229   case X86::VPCMPUDZrmi:     case X86::VPCMPUDZrri:
230   case X86::VPCMPUQZ128rmi:  case X86::VPCMPUQZ128rri:
231   case X86::VPCMPUQZ256rmi:  case X86::VPCMPUQZ256rri:
232   case X86::VPCMPUQZrmi:     case X86::VPCMPUQZrri:
233   case X86::VPCMPUWZ128rmi:  case X86::VPCMPUWZ128rri:
234   case X86::VPCMPUWZ256rmi:  case X86::VPCMPUWZ256rri:
235   case X86::VPCMPUWZrmi:     case X86::VPCMPUWZrri:
236   case X86::VPCMPWZ128rmi:   case X86::VPCMPWZ128rri:
237   case X86::VPCMPWZ256rmi:   case X86::VPCMPWZ256rri:
238   case X86::VPCMPWZrmi:      case X86::VPCMPWZrri:
239   case X86::VPCMPBZ128rmik:  case X86::VPCMPBZ128rrik:
240   case X86::VPCMPBZ256rmik:  case X86::VPCMPBZ256rrik:
241   case X86::VPCMPBZrmik:     case X86::VPCMPBZrrik:
242   case X86::VPCMPDZ128rmik:  case X86::VPCMPDZ128rrik:
243   case X86::VPCMPDZ256rmik:  case X86::VPCMPDZ256rrik:
244   case X86::VPCMPDZrmik:     case X86::VPCMPDZrrik:
245   case X86::VPCMPQZ128rmik:  case X86::VPCMPQZ128rrik:
246   case X86::VPCMPQZ256rmik:  case X86::VPCMPQZ256rrik:
247   case X86::VPCMPQZrmik:     case X86::VPCMPQZrrik:
248   case X86::VPCMPUBZ128rmik: case X86::VPCMPUBZ128rrik:
249   case X86::VPCMPUBZ256rmik: case X86::VPCMPUBZ256rrik:
250   case X86::VPCMPUBZrmik:    case X86::VPCMPUBZrrik:
251   case X86::VPCMPUDZ128rmik: case X86::VPCMPUDZ128rrik:
252   case X86::VPCMPUDZ256rmik: case X86::VPCMPUDZ256rrik:
253   case X86::VPCMPUDZrmik:    case X86::VPCMPUDZrrik:
254   case X86::VPCMPUQZ128rmik: case X86::VPCMPUQZ128rrik:
255   case X86::VPCMPUQZ256rmik: case X86::VPCMPUQZ256rrik:
256   case X86::VPCMPUQZrmik:    case X86::VPCMPUQZrrik:
257   case X86::VPCMPUWZ128rmik: case X86::VPCMPUWZ128rrik:
258   case X86::VPCMPUWZ256rmik: case X86::VPCMPUWZ256rrik:
259   case X86::VPCMPUWZrmik:    case X86::VPCMPUWZrrik:
260   case X86::VPCMPWZ128rmik:  case X86::VPCMPWZ128rrik:
261   case X86::VPCMPWZ256rmik:  case X86::VPCMPWZ256rrik:
262   case X86::VPCMPWZrmik:     case X86::VPCMPWZrrik:
263   case X86::VPCMPDZ128rmib:  case X86::VPCMPDZ128rmibk:
264   case X86::VPCMPDZ256rmib:  case X86::VPCMPDZ256rmibk:
265   case X86::VPCMPDZrmib:     case X86::VPCMPDZrmibk:
266   case X86::VPCMPQZ128rmib:  case X86::VPCMPQZ128rmibk:
267   case X86::VPCMPQZ256rmib:  case X86::VPCMPQZ256rmibk:
268   case X86::VPCMPQZrmib:     case X86::VPCMPQZrmibk:
269   case X86::VPCMPUDZ128rmib: case X86::VPCMPUDZ128rmibk:
270   case X86::VPCMPUDZ256rmib: case X86::VPCMPUDZ256rmibk:
271   case X86::VPCMPUDZrmib:    case X86::VPCMPUDZrmibk:
272   case X86::VPCMPUQZ128rmib: case X86::VPCMPUQZ128rmibk:
273   case X86::VPCMPUQZ256rmib: case X86::VPCMPUQZ256rmibk:
274   case X86::VPCMPUQZrmib:    case X86::VPCMPUQZrmibk:
275     if ((Imm >= 0 && Imm <= 2) || (Imm >= 4 && Imm <= 6)) {
276       OS << '\t';
277       printVPCMPMnemonic(MI, OS);
278 
279       unsigned CurOp = 0;
280       printOperand(MI, CurOp++, OS);
281 
282       if (Desc.TSFlags & X86II::EVEX_K) {
283         // Print mask operand.
284         OS << " {";
285         printOperand(MI, CurOp++, OS);
286         OS << "}";
287       }
288       OS << ", ";
289       printOperand(MI, CurOp++, OS);
290       OS << ", ";
291 
292       if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {
293         if (Desc.TSFlags & X86II::EVEX_B) {
294           // Broadcast form.
295           // Load size is based on W-bit as only D and Q are supported.
296           if (Desc.TSFlags & X86II::VEX_W)
297             printqwordmem(MI, CurOp++, OS);
298           else
299             printdwordmem(MI, CurOp++, OS);
300 
301           // Print the number of elements broadcasted.
302           unsigned NumElts;
303           if (Desc.TSFlags & X86II::EVEX_L2)
304             NumElts = (Desc.TSFlags & X86II::VEX_W) ? 8 : 16;
305           else if (Desc.TSFlags & X86II::VEX_L)
306             NumElts = (Desc.TSFlags & X86II::VEX_W) ? 4 : 8;
307           else
308             NumElts = (Desc.TSFlags & X86II::VEX_W) ? 2 : 4;
309           OS << "{1to" << NumElts << "}";
310         } else {
311           if (Desc.TSFlags & X86II::EVEX_L2)
312             printzmmwordmem(MI, CurOp++, OS);
313           else if (Desc.TSFlags & X86II::VEX_L)
314             printymmwordmem(MI, CurOp++, OS);
315           else
316             printxmmwordmem(MI, CurOp++, OS);
317         }
318       } else {
319         printOperand(MI, CurOp++, OS);
320       }
321 
322       return true;
323     }
324     break;
325   }
326 
327   return false;
328 }
329 
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)330 void X86IntelInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
331                                        raw_ostream &O) {
332   const MCOperand &Op = MI->getOperand(OpNo);
333   if (Op.isReg()) {
334     printRegName(O, Op.getReg());
335   } else if (Op.isImm()) {
336     O << formatImm((int64_t)Op.getImm());
337   } else {
338     assert(Op.isExpr() && "unknown operand kind in printOperand");
339     O << "offset ";
340     Op.getExpr()->print(O, &MAI);
341   }
342 }
343 
printMemReference(const MCInst * MI,unsigned Op,raw_ostream & O)344 void X86IntelInstPrinter::printMemReference(const MCInst *MI, unsigned Op,
345                                             raw_ostream &O) {
346   // Do not print the exact form of the memory operand if it references a known
347   // binary object.
348   if (SymbolizeOperands && MIA) {
349     uint64_t Target;
350     if (MIA->evaluateBranch(*MI, 0, 0, Target))
351       return;
352     if (MIA->evaluateMemoryOperandAddress(*MI, 0, 0))
353       return;
354   }
355   const MCOperand &BaseReg  = MI->getOperand(Op+X86::AddrBaseReg);
356   unsigned ScaleVal         = MI->getOperand(Op+X86::AddrScaleAmt).getImm();
357   const MCOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg);
358   const MCOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp);
359 
360   // If this has a segment register, print it.
361   printOptionalSegReg(MI, Op + X86::AddrSegmentReg, O);
362 
363   O << '[';
364 
365   bool NeedPlus = false;
366   if (BaseReg.getReg()) {
367     printOperand(MI, Op+X86::AddrBaseReg, O);
368     NeedPlus = true;
369   }
370 
371   if (IndexReg.getReg()) {
372     if (NeedPlus) O << " + ";
373     if (ScaleVal != 1)
374       O << ScaleVal << '*';
375     printOperand(MI, Op+X86::AddrIndexReg, O);
376     NeedPlus = true;
377   }
378 
379   if (!DispSpec.isImm()) {
380     if (NeedPlus) O << " + ";
381     assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
382     DispSpec.getExpr()->print(O, &MAI);
383   } else {
384     int64_t DispVal = DispSpec.getImm();
385     if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) {
386       if (NeedPlus) {
387         if (DispVal > 0)
388           O << " + ";
389         else {
390           O << " - ";
391           DispVal = -DispVal;
392         }
393       }
394       O << formatImm(DispVal);
395     }
396   }
397 
398   O << ']';
399 }
400 
printSrcIdx(const MCInst * MI,unsigned Op,raw_ostream & O)401 void X86IntelInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,
402                                       raw_ostream &O) {
403   // If this has a segment register, print it.
404   printOptionalSegReg(MI, Op + 1, O);
405   O << '[';
406   printOperand(MI, Op, O);
407   O << ']';
408 }
409 
printDstIdx(const MCInst * MI,unsigned Op,raw_ostream & O)410 void X86IntelInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,
411                                       raw_ostream &O) {
412   // DI accesses are always ES-based.
413   O << "es:[";
414   printOperand(MI, Op, O);
415   O << ']';
416 }
417 
printMemOffset(const MCInst * MI,unsigned Op,raw_ostream & O)418 void X86IntelInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
419                                          raw_ostream &O) {
420   const MCOperand &DispSpec = MI->getOperand(Op);
421 
422   // If this has a segment register, print it.
423   printOptionalSegReg(MI, Op + 1, O);
424 
425   O << '[';
426 
427   if (DispSpec.isImm()) {
428     O << formatImm(DispSpec.getImm());
429   } else {
430     assert(DispSpec.isExpr() && "non-immediate displacement?");
431     DispSpec.getExpr()->print(O, &MAI);
432   }
433 
434   O << ']';
435 }
436 
printU8Imm(const MCInst * MI,unsigned Op,raw_ostream & O)437 void X86IntelInstPrinter::printU8Imm(const MCInst *MI, unsigned Op,
438                                      raw_ostream &O) {
439   if (MI->getOperand(Op).isExpr())
440     return MI->getOperand(Op).getExpr()->print(O, &MAI);
441 
442   O << formatImm(MI->getOperand(Op).getImm() & 0xff);
443 }
444 
printSTiRegOperand(const MCInst * MI,unsigned OpNo,raw_ostream & OS)445 void X86IntelInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo,
446                                             raw_ostream &OS) {
447   const MCOperand &Op = MI->getOperand(OpNo);
448   unsigned Reg = Op.getReg();
449   // Override the default printing to print st(0) instead st.
450   if (Reg == X86::ST0)
451     OS << "st(0)";
452   else
453     printRegName(OS, Reg);
454 }
455