• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/MCInstrDesc.h"
20 #include "llvm/MC/MCInstrInfo.h"
21 #include "llvm/MC/MCSubtargetInfo.h"
22 #include "llvm/Support/Casting.h"
23 #include "llvm/Support/ErrorHandling.h"
24 #include <cassert>
25 #include <cstdint>
26 
27 using namespace llvm;
28 
29 #define DEBUG_TYPE "asm-printer"
30 
31 // Include the auto-generated portion of the assembly writer.
32 #define PRINT_ALIAS_INSTR
33 #include "X86GenAsmWriter1.inc"
34 
printRegName(raw_ostream & OS,unsigned RegNo) const35 void X86IntelInstPrinter::printRegName(raw_ostream &OS, unsigned RegNo) const {
36   OS << getRegisterName(RegNo);
37 }
38 
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & OS)39 void X86IntelInstPrinter::printInst(const MCInst *MI, uint64_t Address,
40                                     StringRef Annot, const MCSubtargetInfo &STI,
41                                     raw_ostream &OS) {
42   printInstFlags(MI, OS);
43 
44   // In 16-bit mode, print data16 as data32.
45   if (MI->getOpcode() == X86::DATA16_PREFIX &&
46       STI.getFeatureBits()[X86::Mode16Bit]) {
47     OS << "\tdata32";
48   } else if (!printAliasInstr(MI, OS) &&
49              !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   const MCOperand &BaseReg  = MI->getOperand(Op+X86::AddrBaseReg);
347   unsigned ScaleVal         = MI->getOperand(Op+X86::AddrScaleAmt).getImm();
348   const MCOperand &IndexReg = MI->getOperand(Op+X86::AddrIndexReg);
349   const MCOperand &DispSpec = MI->getOperand(Op+X86::AddrDisp);
350 
351   // If this has a segment register, print it.
352   printOptionalSegReg(MI, Op + X86::AddrSegmentReg, O);
353 
354   O << '[';
355 
356   bool NeedPlus = false;
357   if (BaseReg.getReg()) {
358     printOperand(MI, Op+X86::AddrBaseReg, O);
359     NeedPlus = true;
360   }
361 
362   if (IndexReg.getReg()) {
363     if (NeedPlus) O << " + ";
364     if (ScaleVal != 1)
365       O << ScaleVal << '*';
366     printOperand(MI, Op+X86::AddrIndexReg, O);
367     NeedPlus = true;
368   }
369 
370   if (!DispSpec.isImm()) {
371     if (NeedPlus) O << " + ";
372     assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
373     DispSpec.getExpr()->print(O, &MAI);
374   } else {
375     int64_t DispVal = DispSpec.getImm();
376     if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg())) {
377       if (NeedPlus) {
378         if (DispVal > 0)
379           O << " + ";
380         else {
381           O << " - ";
382           DispVal = -DispVal;
383         }
384       }
385       O << formatImm(DispVal);
386     }
387   }
388 
389   O << ']';
390 }
391 
printSrcIdx(const MCInst * MI,unsigned Op,raw_ostream & O)392 void X86IntelInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,
393                                       raw_ostream &O) {
394   // If this has a segment register, print it.
395   printOptionalSegReg(MI, Op + 1, O);
396   O << '[';
397   printOperand(MI, Op, O);
398   O << ']';
399 }
400 
printDstIdx(const MCInst * MI,unsigned Op,raw_ostream & O)401 void X86IntelInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,
402                                       raw_ostream &O) {
403   // DI accesses are always ES-based.
404   O << "es:[";
405   printOperand(MI, Op, O);
406   O << ']';
407 }
408 
printMemOffset(const MCInst * MI,unsigned Op,raw_ostream & O)409 void X86IntelInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
410                                          raw_ostream &O) {
411   const MCOperand &DispSpec = MI->getOperand(Op);
412 
413   // If this has a segment register, print it.
414   printOptionalSegReg(MI, Op + 1, O);
415 
416   O << '[';
417 
418   if (DispSpec.isImm()) {
419     O << formatImm(DispSpec.getImm());
420   } else {
421     assert(DispSpec.isExpr() && "non-immediate displacement?");
422     DispSpec.getExpr()->print(O, &MAI);
423   }
424 
425   O << ']';
426 }
427 
printU8Imm(const MCInst * MI,unsigned Op,raw_ostream & O)428 void X86IntelInstPrinter::printU8Imm(const MCInst *MI, unsigned Op,
429                                      raw_ostream &O) {
430   if (MI->getOperand(Op).isExpr())
431     return MI->getOperand(Op).getExpr()->print(O, &MAI);
432 
433   O << formatImm(MI->getOperand(Op).getImm() & 0xff);
434 }
435 
printSTiRegOperand(const MCInst * MI,unsigned OpNo,raw_ostream & OS)436 void X86IntelInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo,
437                                             raw_ostream &OS) {
438   const MCOperand &Op = MI->getOperand(OpNo);
439   unsigned Reg = Op.getReg();
440   // Override the default printing to print st(0) instead st.
441   if (Reg == X86::ST0)
442     OS << "st(0)";
443   else
444     printRegName(OS, Reg);
445 }
446