10b57cec5SDimitry Andric //===-- X86ATTInstPrinter.cpp - AT&T assembly instruction printing --------===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file includes code for rendering MCInst instances as AT&T-style
100b57cec5SDimitry Andric // assembly.
110b57cec5SDimitry Andric //
120b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
130b57cec5SDimitry Andric
140b57cec5SDimitry Andric #include "X86ATTInstPrinter.h"
150b57cec5SDimitry Andric #include "X86BaseInfo.h"
160b57cec5SDimitry Andric #include "X86InstComments.h"
170b57cec5SDimitry Andric #include "llvm/MC/MCExpr.h"
180b57cec5SDimitry Andric #include "llvm/MC/MCInst.h"
19e8d8bef9SDimitry Andric #include "llvm/MC/MCInstrAnalysis.h"
200b57cec5SDimitry Andric #include "llvm/MC/MCInstrInfo.h"
210b57cec5SDimitry Andric #include "llvm/MC/MCSubtargetInfo.h"
220b57cec5SDimitry Andric #include "llvm/Support/Casting.h"
230b57cec5SDimitry Andric #include "llvm/Support/ErrorHandling.h"
240b57cec5SDimitry Andric #include "llvm/Support/Format.h"
250b57cec5SDimitry Andric #include "llvm/Support/raw_ostream.h"
260b57cec5SDimitry Andric #include <cassert>
270b57cec5SDimitry Andric #include <cinttypes>
280b57cec5SDimitry Andric #include <cstdint>
290b57cec5SDimitry Andric
300b57cec5SDimitry Andric using namespace llvm;
310b57cec5SDimitry Andric
320b57cec5SDimitry Andric #define DEBUG_TYPE "asm-printer"
330b57cec5SDimitry Andric
340b57cec5SDimitry Andric // Include the auto-generated portion of the assembly writer.
350b57cec5SDimitry Andric #define PRINT_ALIAS_INSTR
360b57cec5SDimitry Andric #include "X86GenAsmWriter.inc"
370b57cec5SDimitry Andric
printRegName(raw_ostream & OS,MCRegister Reg) const38bdd1243dSDimitry Andric void X86ATTInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const {
395f757f3fSDimitry Andric markup(OS, Markup::Register) << '%' << getRegisterName(Reg);
400b57cec5SDimitry Andric }
410b57cec5SDimitry Andric
printInst(const MCInst * MI,uint64_t Address,StringRef Annot,const MCSubtargetInfo & STI,raw_ostream & OS)42480093f4SDimitry Andric void X86ATTInstPrinter::printInst(const MCInst *MI, uint64_t Address,
43480093f4SDimitry Andric StringRef Annot, const MCSubtargetInfo &STI,
44480093f4SDimitry Andric raw_ostream &OS) {
450b57cec5SDimitry Andric // If verbose assembly is enabled, we can print some informative comments.
460b57cec5SDimitry Andric if (CommentStream)
470b57cec5SDimitry Andric HasCustomInstComment = EmitAnyX86InstComments(MI, *CommentStream, MII);
480b57cec5SDimitry Andric
4981ad6265SDimitry Andric printInstFlags(MI, OS, STI);
500b57cec5SDimitry Andric
510b57cec5SDimitry Andric // Output CALLpcrel32 as "callq" in 64-bit mode.
520b57cec5SDimitry Andric // In Intel annotation it's always emitted as "call".
530b57cec5SDimitry Andric //
540b57cec5SDimitry Andric // TODO: Probably this hack should be redesigned via InstAlias in
550b57cec5SDimitry Andric // InstrInfo.td as soon as Requires clause is supported properly
560b57cec5SDimitry Andric // for InstAlias.
570b57cec5SDimitry Andric if (MI->getOpcode() == X86::CALLpcrel32 &&
5806c3fb27SDimitry Andric (STI.hasFeature(X86::Is64Bit))) {
590b57cec5SDimitry Andric OS << "\tcallq\t";
605ffd83dbSDimitry Andric printPCRelImm(MI, Address, 0, OS);
610b57cec5SDimitry Andric }
620b57cec5SDimitry Andric // data16 and data32 both have the same encoding of 0x66. While data32 is
630b57cec5SDimitry Andric // valid only in 16 bit systems, data16 is valid in the rest.
640b57cec5SDimitry Andric // There seems to be some lack of support of the Requires clause that causes
650b57cec5SDimitry Andric // 0x66 to be interpreted as "data16" by the asm printer.
660b57cec5SDimitry Andric // Thus we add an adjustment here in order to print the "right" instruction.
670b57cec5SDimitry Andric else if (MI->getOpcode() == X86::DATA16_PREFIX &&
6806c3fb27SDimitry Andric STI.hasFeature(X86::Is16Bit)) {
690b57cec5SDimitry Andric OS << "\tdata32";
700b57cec5SDimitry Andric }
710b57cec5SDimitry Andric // Try to print any aliases first.
725ffd83dbSDimitry Andric else if (!printAliasInstr(MI, Address, OS) && !printVecCompareInstr(MI, OS))
73480093f4SDimitry Andric printInstruction(MI, Address, OS);
740b57cec5SDimitry Andric
750b57cec5SDimitry Andric // Next always print the annotation.
760b57cec5SDimitry Andric printAnnotation(OS, Annot);
770b57cec5SDimitry Andric }
780b57cec5SDimitry Andric
printVecCompareInstr(const MCInst * MI,raw_ostream & OS)790b57cec5SDimitry Andric bool X86ATTInstPrinter::printVecCompareInstr(const MCInst *MI,
800b57cec5SDimitry Andric raw_ostream &OS) {
810b57cec5SDimitry Andric if (MI->getNumOperands() == 0 ||
820b57cec5SDimitry Andric !MI->getOperand(MI->getNumOperands() - 1).isImm())
830b57cec5SDimitry Andric return false;
840b57cec5SDimitry Andric
850b57cec5SDimitry Andric int64_t Imm = MI->getOperand(MI->getNumOperands() - 1).getImm();
860b57cec5SDimitry Andric
870b57cec5SDimitry Andric const MCInstrDesc &Desc = MII.get(MI->getOpcode());
880b57cec5SDimitry Andric
890b57cec5SDimitry Andric // Custom print the vector compare instructions to get the immediate
900b57cec5SDimitry Andric // translated into the mnemonic.
910b57cec5SDimitry Andric switch (MI->getOpcode()) {
920b57cec5SDimitry Andric case X86::CMPPDrmi: case X86::CMPPDrri:
930b57cec5SDimitry Andric case X86::CMPPSrmi: case X86::CMPPSrri:
94*0fca6ea1SDimitry Andric case X86::CMPSDrmi: case X86::CMPSDrri:
95*0fca6ea1SDimitry Andric case X86::CMPSDrmi_Int: case X86::CMPSDrri_Int:
96*0fca6ea1SDimitry Andric case X86::CMPSSrmi: case X86::CMPSSrri:
97*0fca6ea1SDimitry Andric case X86::CMPSSrmi_Int: case X86::CMPSSrri_Int:
980b57cec5SDimitry Andric if (Imm >= 0 && Imm <= 7) {
990b57cec5SDimitry Andric OS << '\t';
1000b57cec5SDimitry Andric printCMPMnemonic(MI, /*IsVCMP*/false, OS);
1010b57cec5SDimitry Andric
1020b57cec5SDimitry Andric if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {
1030b57cec5SDimitry Andric if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS)
1040b57cec5SDimitry Andric printdwordmem(MI, 2, OS);
1050b57cec5SDimitry Andric else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD)
1060b57cec5SDimitry Andric printqwordmem(MI, 2, OS);
1070b57cec5SDimitry Andric else
1080b57cec5SDimitry Andric printxmmwordmem(MI, 2, OS);
1090b57cec5SDimitry Andric } else
1100b57cec5SDimitry Andric printOperand(MI, 2, OS);
1110b57cec5SDimitry Andric
1120b57cec5SDimitry Andric // Skip operand 1 as its tied to the dest.
1130b57cec5SDimitry Andric
1140b57cec5SDimitry Andric OS << ", ";
1150b57cec5SDimitry Andric printOperand(MI, 0, OS);
1160b57cec5SDimitry Andric return true;
1170b57cec5SDimitry Andric }
1180b57cec5SDimitry Andric break;
1190b57cec5SDimitry Andric
1200b57cec5SDimitry Andric case X86::VCMPPDrmi: case X86::VCMPPDrri:
1210b57cec5SDimitry Andric case X86::VCMPPDYrmi: case X86::VCMPPDYrri:
1220b57cec5SDimitry Andric case X86::VCMPPDZ128rmi: case X86::VCMPPDZ128rri:
1230b57cec5SDimitry Andric case X86::VCMPPDZ256rmi: case X86::VCMPPDZ256rri:
1240b57cec5SDimitry Andric case X86::VCMPPDZrmi: case X86::VCMPPDZrri:
1250b57cec5SDimitry Andric case X86::VCMPPSrmi: case X86::VCMPPSrri:
1260b57cec5SDimitry Andric case X86::VCMPPSYrmi: case X86::VCMPPSYrri:
1270b57cec5SDimitry Andric case X86::VCMPPSZ128rmi: case X86::VCMPPSZ128rri:
1280b57cec5SDimitry Andric case X86::VCMPPSZ256rmi: case X86::VCMPPSZ256rri:
1290b57cec5SDimitry Andric case X86::VCMPPSZrmi: case X86::VCMPPSZrri:
130*0fca6ea1SDimitry Andric case X86::VCMPSDrmi: case X86::VCMPSDrri:
131*0fca6ea1SDimitry Andric case X86::VCMPSDZrmi: case X86::VCMPSDZrri:
132*0fca6ea1SDimitry Andric case X86::VCMPSDrmi_Int: case X86::VCMPSDrri_Int:
133*0fca6ea1SDimitry Andric case X86::VCMPSDZrmi_Int: case X86::VCMPSDZrri_Int:
134*0fca6ea1SDimitry Andric case X86::VCMPSSrmi: case X86::VCMPSSrri:
135*0fca6ea1SDimitry Andric case X86::VCMPSSZrmi: case X86::VCMPSSZrri:
136*0fca6ea1SDimitry Andric case X86::VCMPSSrmi_Int: case X86::VCMPSSrri_Int:
137*0fca6ea1SDimitry Andric case X86::VCMPSSZrmi_Int: case X86::VCMPSSZrri_Int:
1380b57cec5SDimitry Andric case X86::VCMPPDZ128rmik: case X86::VCMPPDZ128rrik:
1390b57cec5SDimitry Andric case X86::VCMPPDZ256rmik: case X86::VCMPPDZ256rrik:
1400b57cec5SDimitry Andric case X86::VCMPPDZrmik: case X86::VCMPPDZrrik:
1410b57cec5SDimitry Andric case X86::VCMPPSZ128rmik: case X86::VCMPPSZ128rrik:
1420b57cec5SDimitry Andric case X86::VCMPPSZ256rmik: case X86::VCMPPSZ256rrik:
1430b57cec5SDimitry Andric case X86::VCMPPSZrmik: case X86::VCMPPSZrrik:
144*0fca6ea1SDimitry Andric case X86::VCMPSDZrmi_Intk: case X86::VCMPSDZrri_Intk:
145*0fca6ea1SDimitry Andric case X86::VCMPSSZrmi_Intk: case X86::VCMPSSZrri_Intk:
1460b57cec5SDimitry Andric case X86::VCMPPDZ128rmbi: case X86::VCMPPDZ128rmbik:
1470b57cec5SDimitry Andric case X86::VCMPPDZ256rmbi: case X86::VCMPPDZ256rmbik:
1480b57cec5SDimitry Andric case X86::VCMPPDZrmbi: case X86::VCMPPDZrmbik:
1490b57cec5SDimitry Andric case X86::VCMPPSZ128rmbi: case X86::VCMPPSZ128rmbik:
1500b57cec5SDimitry Andric case X86::VCMPPSZ256rmbi: case X86::VCMPPSZ256rmbik:
1510b57cec5SDimitry Andric case X86::VCMPPSZrmbi: case X86::VCMPPSZrmbik:
1520b57cec5SDimitry Andric case X86::VCMPPDZrrib: case X86::VCMPPDZrribk:
1530b57cec5SDimitry Andric case X86::VCMPPSZrrib: case X86::VCMPPSZrribk:
154*0fca6ea1SDimitry Andric case X86::VCMPSDZrrib_Int: case X86::VCMPSDZrrib_Intk:
155*0fca6ea1SDimitry Andric case X86::VCMPSSZrrib_Int: case X86::VCMPSSZrrib_Intk:
156349cc55cSDimitry Andric case X86::VCMPPHZ128rmi: case X86::VCMPPHZ128rri:
157349cc55cSDimitry Andric case X86::VCMPPHZ256rmi: case X86::VCMPPHZ256rri:
158349cc55cSDimitry Andric case X86::VCMPPHZrmi: case X86::VCMPPHZrri:
159*0fca6ea1SDimitry Andric case X86::VCMPSHZrmi: case X86::VCMPSHZrri:
160*0fca6ea1SDimitry Andric case X86::VCMPSHZrmi_Int: case X86::VCMPSHZrri_Int:
161349cc55cSDimitry Andric case X86::VCMPPHZ128rmik: case X86::VCMPPHZ128rrik:
162349cc55cSDimitry Andric case X86::VCMPPHZ256rmik: case X86::VCMPPHZ256rrik:
163349cc55cSDimitry Andric case X86::VCMPPHZrmik: case X86::VCMPPHZrrik:
164*0fca6ea1SDimitry Andric case X86::VCMPSHZrmi_Intk: case X86::VCMPSHZrri_Intk:
165349cc55cSDimitry Andric case X86::VCMPPHZ128rmbi: case X86::VCMPPHZ128rmbik:
166349cc55cSDimitry Andric case X86::VCMPPHZ256rmbi: case X86::VCMPPHZ256rmbik:
167349cc55cSDimitry Andric case X86::VCMPPHZrmbi: case X86::VCMPPHZrmbik:
168349cc55cSDimitry Andric case X86::VCMPPHZrrib: case X86::VCMPPHZrribk:
169*0fca6ea1SDimitry Andric case X86::VCMPSHZrrib_Int: case X86::VCMPSHZrrib_Intk:
1700b57cec5SDimitry Andric if (Imm >= 0 && Imm <= 31) {
1710b57cec5SDimitry Andric OS << '\t';
1720b57cec5SDimitry Andric printCMPMnemonic(MI, /*IsVCMP*/true, OS);
1730b57cec5SDimitry Andric
1740b57cec5SDimitry Andric unsigned CurOp = (Desc.TSFlags & X86II::EVEX_K) ? 3 : 2;
1750b57cec5SDimitry Andric
1760b57cec5SDimitry Andric if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {
1770b57cec5SDimitry Andric if (Desc.TSFlags & X86II::EVEX_B) {
1780b57cec5SDimitry Andric // Broadcast form.
179349cc55cSDimitry Andric // Load size is word for TA map. Otherwise it is based on W-bit.
180349cc55cSDimitry Andric if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) {
18106c3fb27SDimitry Andric assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!");
182349cc55cSDimitry Andric printwordmem(MI, CurOp--, OS);
18306c3fb27SDimitry Andric } else if (Desc.TSFlags & X86II::REX_W) {
1840b57cec5SDimitry Andric printqwordmem(MI, CurOp--, OS);
185349cc55cSDimitry Andric } else {
1860b57cec5SDimitry Andric printdwordmem(MI, CurOp--, OS);
187349cc55cSDimitry Andric }
1880b57cec5SDimitry Andric
1890b57cec5SDimitry Andric // Print the number of elements broadcasted.
1900b57cec5SDimitry Andric unsigned NumElts;
1910b57cec5SDimitry Andric if (Desc.TSFlags & X86II::EVEX_L2)
19206c3fb27SDimitry Andric NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16;
1930b57cec5SDimitry Andric else if (Desc.TSFlags & X86II::VEX_L)
19406c3fb27SDimitry Andric NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8;
1950b57cec5SDimitry Andric else
19606c3fb27SDimitry Andric NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4;
197349cc55cSDimitry Andric if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA) {
19806c3fb27SDimitry Andric assert(!(Desc.TSFlags & X86II::REX_W) && "Unknown W-bit value!");
199349cc55cSDimitry Andric NumElts *= 2;
200349cc55cSDimitry Andric }
2010b57cec5SDimitry Andric OS << "{1to" << NumElts << "}";
2020b57cec5SDimitry Andric } else {
203349cc55cSDimitry Andric if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XS) {
204349cc55cSDimitry Andric if ((Desc.TSFlags & X86II::OpMapMask) == X86II::TA)
205349cc55cSDimitry Andric printwordmem(MI, CurOp--, OS);
2060b57cec5SDimitry Andric else
207349cc55cSDimitry Andric printdwordmem(MI, CurOp--, OS);
208349cc55cSDimitry Andric } else if ((Desc.TSFlags & X86II::OpPrefixMask) == X86II::XD) {
209349cc55cSDimitry Andric assert((Desc.TSFlags & X86II::OpMapMask) != X86II::TA &&
210349cc55cSDimitry Andric "Unexpected op map!");
211349cc55cSDimitry Andric printqwordmem(MI, CurOp--, OS);
212349cc55cSDimitry Andric } else if (Desc.TSFlags & X86II::EVEX_L2) {
213349cc55cSDimitry Andric printzmmwordmem(MI, CurOp--, OS);
214349cc55cSDimitry Andric } else if (Desc.TSFlags & X86II::VEX_L) {
215349cc55cSDimitry Andric printymmwordmem(MI, CurOp--, OS);
216349cc55cSDimitry Andric } else {
2170b57cec5SDimitry Andric printxmmwordmem(MI, CurOp--, OS);
2180b57cec5SDimitry Andric }
219349cc55cSDimitry Andric }
2200b57cec5SDimitry Andric } else {
2210b57cec5SDimitry Andric if (Desc.TSFlags & X86II::EVEX_B)
2220b57cec5SDimitry Andric OS << "{sae}, ";
2230b57cec5SDimitry Andric printOperand(MI, CurOp--, OS);
2240b57cec5SDimitry Andric }
2250b57cec5SDimitry Andric
2260b57cec5SDimitry Andric OS << ", ";
2270b57cec5SDimitry Andric printOperand(MI, CurOp--, OS);
2280b57cec5SDimitry Andric OS << ", ";
2290b57cec5SDimitry Andric printOperand(MI, 0, OS);
2300b57cec5SDimitry Andric if (CurOp > 0) {
2310b57cec5SDimitry Andric // Print mask operand.
2320b57cec5SDimitry Andric OS << " {";
2330b57cec5SDimitry Andric printOperand(MI, CurOp--, OS);
2340b57cec5SDimitry Andric OS << "}";
2350b57cec5SDimitry Andric }
2360b57cec5SDimitry Andric
2370b57cec5SDimitry Andric return true;
2380b57cec5SDimitry Andric }
2390b57cec5SDimitry Andric break;
2400b57cec5SDimitry Andric
2410b57cec5SDimitry Andric case X86::VPCOMBmi: case X86::VPCOMBri:
2420b57cec5SDimitry Andric case X86::VPCOMDmi: case X86::VPCOMDri:
2430b57cec5SDimitry Andric case X86::VPCOMQmi: case X86::VPCOMQri:
2440b57cec5SDimitry Andric case X86::VPCOMUBmi: case X86::VPCOMUBri:
2450b57cec5SDimitry Andric case X86::VPCOMUDmi: case X86::VPCOMUDri:
2460b57cec5SDimitry Andric case X86::VPCOMUQmi: case X86::VPCOMUQri:
2470b57cec5SDimitry Andric case X86::VPCOMUWmi: case X86::VPCOMUWri:
2480b57cec5SDimitry Andric case X86::VPCOMWmi: case X86::VPCOMWri:
2490b57cec5SDimitry Andric if (Imm >= 0 && Imm <= 7) {
2500b57cec5SDimitry Andric OS << '\t';
2510b57cec5SDimitry Andric printVPCOMMnemonic(MI, OS);
2520b57cec5SDimitry Andric
2530b57cec5SDimitry Andric if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem)
2540b57cec5SDimitry Andric printxmmwordmem(MI, 2, OS);
2550b57cec5SDimitry Andric else
2560b57cec5SDimitry Andric printOperand(MI, 2, OS);
2570b57cec5SDimitry Andric
2580b57cec5SDimitry Andric OS << ", ";
2590b57cec5SDimitry Andric printOperand(MI, 1, OS);
2600b57cec5SDimitry Andric OS << ", ";
2610b57cec5SDimitry Andric printOperand(MI, 0, OS);
2620b57cec5SDimitry Andric return true;
2630b57cec5SDimitry Andric }
2640b57cec5SDimitry Andric break;
2650b57cec5SDimitry Andric
2660b57cec5SDimitry Andric case X86::VPCMPBZ128rmi: case X86::VPCMPBZ128rri:
2670b57cec5SDimitry Andric case X86::VPCMPBZ256rmi: case X86::VPCMPBZ256rri:
2680b57cec5SDimitry Andric case X86::VPCMPBZrmi: case X86::VPCMPBZrri:
2690b57cec5SDimitry Andric case X86::VPCMPDZ128rmi: case X86::VPCMPDZ128rri:
2700b57cec5SDimitry Andric case X86::VPCMPDZ256rmi: case X86::VPCMPDZ256rri:
2710b57cec5SDimitry Andric case X86::VPCMPDZrmi: case X86::VPCMPDZrri:
2720b57cec5SDimitry Andric case X86::VPCMPQZ128rmi: case X86::VPCMPQZ128rri:
2730b57cec5SDimitry Andric case X86::VPCMPQZ256rmi: case X86::VPCMPQZ256rri:
2740b57cec5SDimitry Andric case X86::VPCMPQZrmi: case X86::VPCMPQZrri:
2750b57cec5SDimitry Andric case X86::VPCMPUBZ128rmi: case X86::VPCMPUBZ128rri:
2760b57cec5SDimitry Andric case X86::VPCMPUBZ256rmi: case X86::VPCMPUBZ256rri:
2770b57cec5SDimitry Andric case X86::VPCMPUBZrmi: case X86::VPCMPUBZrri:
2780b57cec5SDimitry Andric case X86::VPCMPUDZ128rmi: case X86::VPCMPUDZ128rri:
2790b57cec5SDimitry Andric case X86::VPCMPUDZ256rmi: case X86::VPCMPUDZ256rri:
2800b57cec5SDimitry Andric case X86::VPCMPUDZrmi: case X86::VPCMPUDZrri:
2810b57cec5SDimitry Andric case X86::VPCMPUQZ128rmi: case X86::VPCMPUQZ128rri:
2820b57cec5SDimitry Andric case X86::VPCMPUQZ256rmi: case X86::VPCMPUQZ256rri:
2830b57cec5SDimitry Andric case X86::VPCMPUQZrmi: case X86::VPCMPUQZrri:
2840b57cec5SDimitry Andric case X86::VPCMPUWZ128rmi: case X86::VPCMPUWZ128rri:
2850b57cec5SDimitry Andric case X86::VPCMPUWZ256rmi: case X86::VPCMPUWZ256rri:
2860b57cec5SDimitry Andric case X86::VPCMPUWZrmi: case X86::VPCMPUWZrri:
2870b57cec5SDimitry Andric case X86::VPCMPWZ128rmi: case X86::VPCMPWZ128rri:
2880b57cec5SDimitry Andric case X86::VPCMPWZ256rmi: case X86::VPCMPWZ256rri:
2890b57cec5SDimitry Andric case X86::VPCMPWZrmi: case X86::VPCMPWZrri:
2900b57cec5SDimitry Andric case X86::VPCMPBZ128rmik: case X86::VPCMPBZ128rrik:
2910b57cec5SDimitry Andric case X86::VPCMPBZ256rmik: case X86::VPCMPBZ256rrik:
2920b57cec5SDimitry Andric case X86::VPCMPBZrmik: case X86::VPCMPBZrrik:
2930b57cec5SDimitry Andric case X86::VPCMPDZ128rmik: case X86::VPCMPDZ128rrik:
2940b57cec5SDimitry Andric case X86::VPCMPDZ256rmik: case X86::VPCMPDZ256rrik:
2950b57cec5SDimitry Andric case X86::VPCMPDZrmik: case X86::VPCMPDZrrik:
2960b57cec5SDimitry Andric case X86::VPCMPQZ128rmik: case X86::VPCMPQZ128rrik:
2970b57cec5SDimitry Andric case X86::VPCMPQZ256rmik: case X86::VPCMPQZ256rrik:
2980b57cec5SDimitry Andric case X86::VPCMPQZrmik: case X86::VPCMPQZrrik:
2990b57cec5SDimitry Andric case X86::VPCMPUBZ128rmik: case X86::VPCMPUBZ128rrik:
3000b57cec5SDimitry Andric case X86::VPCMPUBZ256rmik: case X86::VPCMPUBZ256rrik:
3010b57cec5SDimitry Andric case X86::VPCMPUBZrmik: case X86::VPCMPUBZrrik:
3020b57cec5SDimitry Andric case X86::VPCMPUDZ128rmik: case X86::VPCMPUDZ128rrik:
3030b57cec5SDimitry Andric case X86::VPCMPUDZ256rmik: case X86::VPCMPUDZ256rrik:
3040b57cec5SDimitry Andric case X86::VPCMPUDZrmik: case X86::VPCMPUDZrrik:
3050b57cec5SDimitry Andric case X86::VPCMPUQZ128rmik: case X86::VPCMPUQZ128rrik:
3060b57cec5SDimitry Andric case X86::VPCMPUQZ256rmik: case X86::VPCMPUQZ256rrik:
3070b57cec5SDimitry Andric case X86::VPCMPUQZrmik: case X86::VPCMPUQZrrik:
3080b57cec5SDimitry Andric case X86::VPCMPUWZ128rmik: case X86::VPCMPUWZ128rrik:
3090b57cec5SDimitry Andric case X86::VPCMPUWZ256rmik: case X86::VPCMPUWZ256rrik:
3100b57cec5SDimitry Andric case X86::VPCMPUWZrmik: case X86::VPCMPUWZrrik:
3110b57cec5SDimitry Andric case X86::VPCMPWZ128rmik: case X86::VPCMPWZ128rrik:
3120b57cec5SDimitry Andric case X86::VPCMPWZ256rmik: case X86::VPCMPWZ256rrik:
3130b57cec5SDimitry Andric case X86::VPCMPWZrmik: case X86::VPCMPWZrrik:
3140b57cec5SDimitry Andric case X86::VPCMPDZ128rmib: case X86::VPCMPDZ128rmibk:
3150b57cec5SDimitry Andric case X86::VPCMPDZ256rmib: case X86::VPCMPDZ256rmibk:
3160b57cec5SDimitry Andric case X86::VPCMPDZrmib: case X86::VPCMPDZrmibk:
3170b57cec5SDimitry Andric case X86::VPCMPQZ128rmib: case X86::VPCMPQZ128rmibk:
3180b57cec5SDimitry Andric case X86::VPCMPQZ256rmib: case X86::VPCMPQZ256rmibk:
3190b57cec5SDimitry Andric case X86::VPCMPQZrmib: case X86::VPCMPQZrmibk:
3200b57cec5SDimitry Andric case X86::VPCMPUDZ128rmib: case X86::VPCMPUDZ128rmibk:
3210b57cec5SDimitry Andric case X86::VPCMPUDZ256rmib: case X86::VPCMPUDZ256rmibk:
3220b57cec5SDimitry Andric case X86::VPCMPUDZrmib: case X86::VPCMPUDZrmibk:
3230b57cec5SDimitry Andric case X86::VPCMPUQZ128rmib: case X86::VPCMPUQZ128rmibk:
3240b57cec5SDimitry Andric case X86::VPCMPUQZ256rmib: case X86::VPCMPUQZ256rmibk:
3250b57cec5SDimitry Andric case X86::VPCMPUQZrmib: case X86::VPCMPUQZrmibk:
3260b57cec5SDimitry Andric if ((Imm >= 0 && Imm <= 2) || (Imm >= 4 && Imm <= 6)) {
3270b57cec5SDimitry Andric OS << '\t';
3280b57cec5SDimitry Andric printVPCMPMnemonic(MI, OS);
3290b57cec5SDimitry Andric
3300b57cec5SDimitry Andric unsigned CurOp = (Desc.TSFlags & X86II::EVEX_K) ? 3 : 2;
3310b57cec5SDimitry Andric
3320b57cec5SDimitry Andric if ((Desc.TSFlags & X86II::FormMask) == X86II::MRMSrcMem) {
3330b57cec5SDimitry Andric if (Desc.TSFlags & X86II::EVEX_B) {
3340b57cec5SDimitry Andric // Broadcast form.
3350b57cec5SDimitry Andric // Load size is based on W-bit as only D and Q are supported.
33606c3fb27SDimitry Andric if (Desc.TSFlags & X86II::REX_W)
3370b57cec5SDimitry Andric printqwordmem(MI, CurOp--, OS);
3380b57cec5SDimitry Andric else
3390b57cec5SDimitry Andric printdwordmem(MI, CurOp--, OS);
3400b57cec5SDimitry Andric
3410b57cec5SDimitry Andric // Print the number of elements broadcasted.
3420b57cec5SDimitry Andric unsigned NumElts;
3430b57cec5SDimitry Andric if (Desc.TSFlags & X86II::EVEX_L2)
34406c3fb27SDimitry Andric NumElts = (Desc.TSFlags & X86II::REX_W) ? 8 : 16;
3450b57cec5SDimitry Andric else if (Desc.TSFlags & X86II::VEX_L)
34606c3fb27SDimitry Andric NumElts = (Desc.TSFlags & X86II::REX_W) ? 4 : 8;
3470b57cec5SDimitry Andric else
34806c3fb27SDimitry Andric NumElts = (Desc.TSFlags & X86II::REX_W) ? 2 : 4;
3490b57cec5SDimitry Andric OS << "{1to" << NumElts << "}";
3500b57cec5SDimitry Andric } else {
3510b57cec5SDimitry Andric if (Desc.TSFlags & X86II::EVEX_L2)
3520b57cec5SDimitry Andric printzmmwordmem(MI, CurOp--, OS);
3530b57cec5SDimitry Andric else if (Desc.TSFlags & X86II::VEX_L)
3540b57cec5SDimitry Andric printymmwordmem(MI, CurOp--, OS);
3550b57cec5SDimitry Andric else
3560b57cec5SDimitry Andric printxmmwordmem(MI, CurOp--, OS);
3570b57cec5SDimitry Andric }
3580b57cec5SDimitry Andric } else {
3590b57cec5SDimitry Andric printOperand(MI, CurOp--, OS);
3600b57cec5SDimitry Andric }
3610b57cec5SDimitry Andric
3620b57cec5SDimitry Andric OS << ", ";
3630b57cec5SDimitry Andric printOperand(MI, CurOp--, OS);
3640b57cec5SDimitry Andric OS << ", ";
3650b57cec5SDimitry Andric printOperand(MI, 0, OS);
3660b57cec5SDimitry Andric if (CurOp > 0) {
3670b57cec5SDimitry Andric // Print mask operand.
3680b57cec5SDimitry Andric OS << " {";
3690b57cec5SDimitry Andric printOperand(MI, CurOp--, OS);
3700b57cec5SDimitry Andric OS << "}";
3710b57cec5SDimitry Andric }
3720b57cec5SDimitry Andric
3730b57cec5SDimitry Andric return true;
3740b57cec5SDimitry Andric }
3750b57cec5SDimitry Andric break;
3760b57cec5SDimitry Andric }
3770b57cec5SDimitry Andric
3780b57cec5SDimitry Andric return false;
3790b57cec5SDimitry Andric }
3800b57cec5SDimitry Andric
printOperand(const MCInst * MI,unsigned OpNo,raw_ostream & O)3810b57cec5SDimitry Andric void X86ATTInstPrinter::printOperand(const MCInst *MI, unsigned OpNo,
3820b57cec5SDimitry Andric raw_ostream &O) {
3830b57cec5SDimitry Andric const MCOperand &Op = MI->getOperand(OpNo);
3840b57cec5SDimitry Andric if (Op.isReg()) {
3850b57cec5SDimitry Andric printRegName(O, Op.getReg());
3860b57cec5SDimitry Andric } else if (Op.isImm()) {
3870b57cec5SDimitry Andric // Print immediates as signed values.
3880b57cec5SDimitry Andric int64_t Imm = Op.getImm();
3895f757f3fSDimitry Andric markup(O, Markup::Immediate) << '$' << formatImm(Imm);
3900b57cec5SDimitry Andric
3910b57cec5SDimitry Andric // TODO: This should be in a helper function in the base class, so it can
3920b57cec5SDimitry Andric // be used by other printers.
3930b57cec5SDimitry Andric
3940b57cec5SDimitry Andric // If there are no instruction-specific comments, add a comment clarifying
3950b57cec5SDimitry Andric // the hex value of the immediate operand when it isn't in the range
3960b57cec5SDimitry Andric // [-256,255].
3970b57cec5SDimitry Andric if (CommentStream && !HasCustomInstComment && (Imm > 255 || Imm < -256)) {
3980b57cec5SDimitry Andric // Don't print unnecessary hex sign bits.
3990b57cec5SDimitry Andric if (Imm == (int16_t)(Imm))
4000b57cec5SDimitry Andric *CommentStream << format("imm = 0x%" PRIX16 "\n", (uint16_t)Imm);
4010b57cec5SDimitry Andric else if (Imm == (int32_t)(Imm))
4020b57cec5SDimitry Andric *CommentStream << format("imm = 0x%" PRIX32 "\n", (uint32_t)Imm);
4030b57cec5SDimitry Andric else
4040b57cec5SDimitry Andric *CommentStream << format("imm = 0x%" PRIX64 "\n", (uint64_t)Imm);
4050b57cec5SDimitry Andric }
4060b57cec5SDimitry Andric } else {
4070b57cec5SDimitry Andric assert(Op.isExpr() && "unknown operand kind in printOperand");
4085f757f3fSDimitry Andric WithMarkup M = markup(O, Markup::Immediate);
4095f757f3fSDimitry Andric O << '$';
4100b57cec5SDimitry Andric Op.getExpr()->print(O, &MAI);
4110b57cec5SDimitry Andric }
4120b57cec5SDimitry Andric }
4130b57cec5SDimitry Andric
printMemReference(const MCInst * MI,unsigned Op,raw_ostream & O)4140b57cec5SDimitry Andric void X86ATTInstPrinter::printMemReference(const MCInst *MI, unsigned Op,
4150b57cec5SDimitry Andric raw_ostream &O) {
416e8d8bef9SDimitry Andric // Do not print the exact form of the memory operand if it references a known
417e8d8bef9SDimitry Andric // binary object.
418e8d8bef9SDimitry Andric if (SymbolizeOperands && MIA) {
419e8d8bef9SDimitry Andric uint64_t Target;
420e8d8bef9SDimitry Andric if (MIA->evaluateBranch(*MI, 0, 0, Target))
421e8d8bef9SDimitry Andric return;
422349cc55cSDimitry Andric if (MIA->evaluateMemoryOperandAddress(*MI, /*STI=*/nullptr, 0, 0))
423e8d8bef9SDimitry Andric return;
424e8d8bef9SDimitry Andric }
425e8d8bef9SDimitry Andric
4260b57cec5SDimitry Andric const MCOperand &BaseReg = MI->getOperand(Op + X86::AddrBaseReg);
4270b57cec5SDimitry Andric const MCOperand &IndexReg = MI->getOperand(Op + X86::AddrIndexReg);
4280b57cec5SDimitry Andric const MCOperand &DispSpec = MI->getOperand(Op + X86::AddrDisp);
4290b57cec5SDimitry Andric
4305f757f3fSDimitry Andric WithMarkup M = markup(O, Markup::Memory);
4310b57cec5SDimitry Andric
4320b57cec5SDimitry Andric // If this has a segment register, print it.
4330b57cec5SDimitry Andric printOptionalSegReg(MI, Op + X86::AddrSegmentReg, O);
4340b57cec5SDimitry Andric
4350b57cec5SDimitry Andric if (DispSpec.isImm()) {
4360b57cec5SDimitry Andric int64_t DispVal = DispSpec.getImm();
4370b57cec5SDimitry Andric if (DispVal || (!IndexReg.getReg() && !BaseReg.getReg()))
4380b57cec5SDimitry Andric O << formatImm(DispVal);
4390b57cec5SDimitry Andric } else {
4400b57cec5SDimitry Andric assert(DispSpec.isExpr() && "non-immediate displacement for LEA?");
4410b57cec5SDimitry Andric DispSpec.getExpr()->print(O, &MAI);
4420b57cec5SDimitry Andric }
4430b57cec5SDimitry Andric
4440b57cec5SDimitry Andric if (IndexReg.getReg() || BaseReg.getReg()) {
4450b57cec5SDimitry Andric O << '(';
4460b57cec5SDimitry Andric if (BaseReg.getReg())
4470b57cec5SDimitry Andric printOperand(MI, Op + X86::AddrBaseReg, O);
4480b57cec5SDimitry Andric
4490b57cec5SDimitry Andric if (IndexReg.getReg()) {
4500b57cec5SDimitry Andric O << ',';
4510b57cec5SDimitry Andric printOperand(MI, Op + X86::AddrIndexReg, O);
4520b57cec5SDimitry Andric unsigned ScaleVal = MI->getOperand(Op + X86::AddrScaleAmt).getImm();
4530b57cec5SDimitry Andric if (ScaleVal != 1) {
4545f757f3fSDimitry Andric O << ',';
4555f757f3fSDimitry Andric markup(O, Markup::Immediate) << ScaleVal; // never printed in hex.
4560b57cec5SDimitry Andric }
4570b57cec5SDimitry Andric }
4580b57cec5SDimitry Andric O << ')';
4590b57cec5SDimitry Andric }
4600b57cec5SDimitry Andric }
4610b57cec5SDimitry Andric
printSrcIdx(const MCInst * MI,unsigned Op,raw_ostream & O)4620b57cec5SDimitry Andric void X86ATTInstPrinter::printSrcIdx(const MCInst *MI, unsigned Op,
4630b57cec5SDimitry Andric raw_ostream &O) {
4645f757f3fSDimitry Andric WithMarkup M = markup(O, Markup::Memory);
4650b57cec5SDimitry Andric
4660b57cec5SDimitry Andric // If this has a segment register, print it.
4670b57cec5SDimitry Andric printOptionalSegReg(MI, Op + 1, O);
4680b57cec5SDimitry Andric
4690b57cec5SDimitry Andric O << "(";
4700b57cec5SDimitry Andric printOperand(MI, Op, O);
4710b57cec5SDimitry Andric O << ")";
4720b57cec5SDimitry Andric }
4730b57cec5SDimitry Andric
printDstIdx(const MCInst * MI,unsigned Op,raw_ostream & O)4740b57cec5SDimitry Andric void X86ATTInstPrinter::printDstIdx(const MCInst *MI, unsigned Op,
4750b57cec5SDimitry Andric raw_ostream &O) {
4765f757f3fSDimitry Andric WithMarkup M = markup(O, Markup::Memory);
4770b57cec5SDimitry Andric
4780b57cec5SDimitry Andric O << "%es:(";
4790b57cec5SDimitry Andric printOperand(MI, Op, O);
4800b57cec5SDimitry Andric O << ")";
4810b57cec5SDimitry Andric }
4820b57cec5SDimitry Andric
printMemOffset(const MCInst * MI,unsigned Op,raw_ostream & O)4830b57cec5SDimitry Andric void X86ATTInstPrinter::printMemOffset(const MCInst *MI, unsigned Op,
4840b57cec5SDimitry Andric raw_ostream &O) {
4850b57cec5SDimitry Andric const MCOperand &DispSpec = MI->getOperand(Op);
4860b57cec5SDimitry Andric
4875f757f3fSDimitry Andric WithMarkup M = markup(O, Markup::Memory);
4880b57cec5SDimitry Andric
4890b57cec5SDimitry Andric // If this has a segment register, print it.
4900b57cec5SDimitry Andric printOptionalSegReg(MI, Op + 1, O);
4910b57cec5SDimitry Andric
4920b57cec5SDimitry Andric if (DispSpec.isImm()) {
4930b57cec5SDimitry Andric O << formatImm(DispSpec.getImm());
4940b57cec5SDimitry Andric } else {
4950b57cec5SDimitry Andric assert(DispSpec.isExpr() && "non-immediate displacement?");
4960b57cec5SDimitry Andric DispSpec.getExpr()->print(O, &MAI);
4970b57cec5SDimitry Andric }
4980b57cec5SDimitry Andric }
4990b57cec5SDimitry Andric
printU8Imm(const MCInst * MI,unsigned Op,raw_ostream & O)5000b57cec5SDimitry Andric void X86ATTInstPrinter::printU8Imm(const MCInst *MI, unsigned Op,
5010b57cec5SDimitry Andric raw_ostream &O) {
5020b57cec5SDimitry Andric if (MI->getOperand(Op).isExpr())
5030b57cec5SDimitry Andric return printOperand(MI, Op, O);
5040b57cec5SDimitry Andric
5055f757f3fSDimitry Andric markup(O, Markup::Immediate)
5065f757f3fSDimitry Andric << '$' << formatImm(MI->getOperand(Op).getImm() & 0xff);
5070b57cec5SDimitry Andric }
5080b57cec5SDimitry Andric
printSTiRegOperand(const MCInst * MI,unsigned OpNo,raw_ostream & OS)5090b57cec5SDimitry Andric void X86ATTInstPrinter::printSTiRegOperand(const MCInst *MI, unsigned OpNo,
5100b57cec5SDimitry Andric raw_ostream &OS) {
5110b57cec5SDimitry Andric const MCOperand &Op = MI->getOperand(OpNo);
5120b57cec5SDimitry Andric unsigned Reg = Op.getReg();
5130b57cec5SDimitry Andric // Override the default printing to print st(0) instead st.
5140b57cec5SDimitry Andric if (Reg == X86::ST0)
5155f757f3fSDimitry Andric markup(OS, Markup::Register) << "%st(0)";
5160b57cec5SDimitry Andric else
5170b57cec5SDimitry Andric printRegName(OS, Reg);
5180b57cec5SDimitry Andric }
519