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