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 38bdd1243dSDimitry Andric void X86ATTInstPrinter::printRegName(raw_ostream &OS, MCRegister Reg) const { 395f757f3fSDimitry Andric markup(OS, Markup::Register) << '%' << getRegisterName(Reg); 400b57cec5SDimitry Andric } 410b57cec5SDimitry Andric 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 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 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 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 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 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 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 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 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